[TIOJ] 1045. A.細菌培養

題目連結:http://tioj.infor.org/problems/1045
原本看到的時候想用線段樹直接揍他,結果寫一寫覺得卡卡的,然後就被嗆說幹嘛用線段樹做了QQ。想了想才發現可以離散化後直接對序列操作,複雜度$O(N^2)$,也就是把序列乘二或除二,然後算一下他的變化量來維護整段的總和。
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
typedef long long lld;
#define ALL(x) (x).begin(), (x).end()

const int N = 10000 + 1;

class Lisan{
	private:
		vector<int> v;
	public:
		inline void init(){
			v.clear();
		}
		inline void insert(int x){
			v.PB(x);
		}
		inline void done(){
			sort(ALL(v));
			v.resize(distance(v.begin(), unique(ALL(v))));
		}
		inline int get(int x){
			return distance(v.begin(), lower_bound(ALL(v),x));
		}
		inline int inv_get(int x){
			return v[x];
		}
} li;

struct Opt{
	int pos, l, r, v;
};
vector<Opt> opts;
lld arr[N], sum=0;
inline void init();
inline void mul(int,int,double);

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	int n;
	while(cin>>n, n){
		init();
		for(int i=0;i<n;i++){
			int l, t, r, b;
			cin>>l>>t>>r>>b;
			opts.PB({l,t,b,1});
			opts.PB({r,t,b,0});
			li.insert(t);
			li.insert(b);
		}
		li.done();
		sort(ALL(opts),[](const Opt &a, const Opt &b){return a.pos<b.pos;});
		lld ans = 0;
		int prePos = 0;
		for(auto i:opts){
			ans += (i.pos-prePos)*sum;
			mul(li.get(i.l),li.get(i.r),(i.v?2:0.5));
			prePos = i.pos;
		}
		ans += (N-1-prePos)*sum;
		cout<<ans<<'\n';
	}
	return 0;
}

inline void init(){
	fill(arr,arr+N,1);
	sum=N-1;
	opts.clear();
	li.init();
}

inline void mul(int l, int r, double x){
	for(int i=l;i<r;i++){
		sum += ((lld)(arr[i]*x) - arr[i])*(li.inv_get(i+1)-li.inv_get(i));
		arr[i]*=x;
	}
}

留言

這個網誌中的熱門文章

[TIOJ] 1902. 「殿仁.王,不認識,誰啊?」,然後他就死了……

[AtCoder] [經典競程 90 題] 024 - Select +/- One(★2)

[AtCoder] [經典競程 90 題] 022 - Cubic Cake(★2)