[Poi2011]Meteors

题意

思路:

首先可以感觉到是二分
进而可以发现是整体二分
警告:后面做法极为骚气,请各位站稳扶牢
这里的插入操作可以看成每一次的区间加(如果l>r可拆为两边处理)
最后可强行加一个覆盖所有点的区间加1e9,这样能满足所有p[i]
这里的询问操作可以看成询问每一个点的权值
对于整体二分基本与其他的相同,
不同的是需要扫整个区间,对区间内的每个国家收集到的陨石数进行统计,设它为num
若num>=p[i],直接将它装入左半部分递归
若num<p[i],则需p[i]-=num,然后再进入右半部分递归

具体实现:

对于区间加单点查询可使用差分的树状数组
用flag数组记录每个点所属国家在此次陨石收集过程中是否已被满足

很好。然鹅提交上去总会WA几个点
于是乎发现加的时候会爆int,于是乎开long long
于是乎发现又WA,于是乎发现加的时候连long long都会爆
怎么办呢?回首一看p[i]<=1e9。加到1e9不加了不就好了吗。

注意事项:

相加的时候的数据范围。

code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+5;
int n,m,k,cnt;
int o[N],flag[N],ans[N];
ll gt[N],p[N];
struct node{int l,r,v,id,tp;}q[N*3],q1[N*3],q2[N*3];
inline int read()
{
	int s=0,w=1; char ch=getchar();
	for(;'0'>ch||ch>'9';ch=getchar())if(ch=='-')w=-1;
	for(;'0'<=ch&&ch<='9';ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
	return s*w;
}
struct tree{
	ll c[N];
	inline int lowbit(int x){return x&(-x);}
	inline void add(int x,ll y)
	{
		for(;x<=m;x+=lowbit(x))c[x]+=y;
	}
	inline ll query(int x)
	{
		ll anss=0;
		for(;x;x-=lowbit(x))anss+=c[x];
		return anss;
	}
}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)
			if(q[i].tp==2) ans[q[i].id]=L;
		return;
	}
	for(int i=l;i<=r;++i)if(q[i].tp==2)gt[q[i].id]=0,flag[q[i].id]=-1;
	int mid=L+R>>1,cnt1=0,cnt2=0;
	for(int i=l;i<=r;++i)
	{
		if(q[i].tp==1)
		{
			if(q[i].id<=mid) 
				T.add(q[i].l,1ll*q[i].v),T.add(q[i].r+1,-1ll*q[i].v),q1[++cnt1]=q[i];
			else q2[++cnt2]=q[i];
		}
		else gt[q[i].id]=min(1000000001ll,gt[q[i].id]+T.query(q[i].l));
	}
	for(int i=l;i<=r;++i)
	{
		if(q[i].tp==1)
		{
			if(q[i].id<=mid) T.add(q[i].l,-1ll*q[i].v),T.add(q[i].r+1,1ll*q[i].v);
			continue;
		} 
		int pos=q[i].id;
		if(flag[pos]==1) q1[++cnt1]=q[i];
		else if(flag[pos]==0) q2[++cnt2]=q[i];
		else
		{
			if(gt[pos]>=p[pos]) flag[pos]=1,q1[++cnt1]=q[i];
			else p[pos]-=gt[pos],flag[pos]=0,q2[++cnt2]=q[i];
		}
	}
	for(int i=l;i<=l+cnt1-1;++i) q[i]=q1[i-l+1];
	for(int i=l+cnt1;i<=r;++i) q[i]=q2[i-l-cnt1+1];
	solve(L,mid,l,l+cnt1-1);
	solve(mid+1,R,l+cnt1,r);
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<=m;++i)o[i]=read();
	for(int i=1;i<=n;++i)p[i]=1ll*read();
	k=read();
	for(int i=1;i<=k;++i)
	{
		int li=read(),ri=read(),ai=read();
		if(li<=ri) q[++cnt]=node{li,ri,ai,i,1};
		else
		{
			q[++cnt]=node{1,ri,ai,i,1};
			q[++cnt]=node{li,m,ai,i,1};
		}
	}
	q[++cnt]=node{1,m,1e9,k+1,1};
	for(int i=1;i<=m;++i)q[++cnt]=node{i,0,0,o[i],2};
	solve(1,k+1,1,cnt);
	for(int i=1;i<=n;++i)
	{
		if(ans[i]==k+1||ans[i]==0) puts("NIE");
		else printf("%d\n",ans[i]);
	}
	return 0;
}
posted @ 2019-12-14 22:59  BILL666  阅读(145)  评论(0编辑  收藏  举报