cunzai_zsy0531

关注我

P3527 [POI2011]MET-Meteors 题解

题面

考虑整体二分。solve(L,R,l,r) 表示解决的子问题为答案区间在 \([L,R]\) 内的所有问题 \(q_l...q_r\)。边界条件很容易,主要是考虑如何二分。\([L,R]\) 这一维相当于是描述的时间,那么考虑一个 \(mid\),然后把所有 \([L,mid]\) 时刻的修改加进树状数组,这样区间和就变成单点修改了。然后扫一遍 \([L,R]\) 的询问,如果此时已经满足条件,说明它的答案区间为 \([L,mid]\),否则是 \([mid+1,R]\)。复杂度为 \(O(n\log m\log k)\)

注意加和可能爆ll,所以需要边加边判断;注意不要使用 memset,虽然其有小常数,但是复杂度可能会多一个 \(\log\) 导致TLE!

点击查看代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
inline int min(const int &x,const int &y){return x<y?x:y;}
inline int rd(){
	int res=0;char c=getchar();
	for(;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())res=(res<<1)+(res<<3)+(c-'0');
	return res;
}
void wt(int x){if(x>9)wt(x/10);putchar(x%10+'0');}
const int N=3e5+13;
int n,m,k,b[N],q[N],lq[N],rq[N],ans[N];
vector<int> a[N];
struct Node{int l,r,w;}c[N];
struct BIT{
	ll t[N];
	#define lowbit(x) (x&-x)
	inline void add(int x,int k){for(;x<=m;x+=lowbit(x))t[x]+=k;}
	inline ll sum(int x){ll res=0;for(;x;x-=lowbit(x))res+=t[x];return res;}
}T;
void solve(int L,int R,int l,int r){
	if(l>r) return;
	if(L==R){
		for(int i=l;i<=r;++i) ans[q[i]]=L;
		return;
	}
	int mid=(L+R)>>1;
	for(int i=L;i<=min(mid,k);++i){
		if(c[i].l<=c[i].r) T.add(c[i].l,c[i].w),T.add(c[i].r+1,-c[i].w);
		else T.add(1,c[i].w),T.add(c[i].r+1,-c[i].w),T.add(c[i].l,c[i].w);
	}
	int lt=0,rt=0;
	for(int i=l;i<=r;++i){
		ll res=0;int lim=a[q[i]].size();bool flag=1;
		for(int j=0;j<lim;++j){
			res+=T.sum(a[q[i]][j]);
			if(res>=b[q[i]]){flag=0;break;}
		}
		if(!flag) lq[++lt]=q[i];
		else rq[++rt]=q[i],b[q[i]]-=res;
	}
	for(int i=L;i<=min(mid,k);++i){
		if(c[i].l<=c[i].r) T.add(c[i].l,-c[i].w),T.add(c[i].r+1,c[i].w);
		else T.add(1,-c[i].w),T.add(c[i].r+1,c[i].w),T.add(c[i].l,-c[i].w);
	}
	for(int i=1;i<=lt;++i) q[l+i-1]=lq[i];
	for(int i=1;i<=rt;++i) q[l+lt+i-1]=rq[i];
	solve(L,mid,l,l+lt-1);
	solve(mid+1,R,l+lt,r);
}
int main(){
	n=rd(),m=rd();
	for(int i=1,x;i<=m;++i){
		x=rd();
		a[x].push_back(i);
	}
	for(int i=1;i<=n;++i) b[i]=rd();
	k=rd();
	for(int i=1;i<=k;++i) c[i].l=rd(),c[i].r=rd(),c[i].w=rd();
	for(int i=1;i<=n;++i) q[i]=i;
	solve(1,k+1,1,n);
	for(int i=1;i<=n;++i){
		if(ans[i]==k+1) puts("NIE");
		else wt(ans[i]),putchar('\n');
	}
	return 0;
}
posted @ 2022-05-18 20:03  cunzai_zsy0531  阅读(25)  评论(0编辑  收藏  举报