bzoj-2527 Meteors

来源:互联网 发布:js获取div的id值 编辑:程序博客网 时间:2024/05/18 03:50

题意:

有一个星球,它的轨道被划分成m份,由n个国家占领;

一个国家可能占领多个轨道段;

现有q次事件,每次在一个轨道区间上每段落下Ai量的流星雨;

每个国家需要一定量的流星雨,当然它所得的为它占领的轨道段所得之和;

求每个国家所需的东西什么时候可以满足,如果始终不能满足输出NIE;


题解:

这题我第一眼看成了输出TAK或NIE;

结果仔细看看我选择死亡;

边处理事件边判断是否满足答案这个复杂度无论如何都无法接受;

所以要将事件离线下来处理;

另一个思路就是可持久化线段树;

建树的时候只会更改logm个结点,复杂度O(qlogm);

查询二分答案,复杂度O(n*logq*logm);

这样的时间复杂度是可以的啦,然而我们来算算空间;

线段树里要开qlogm个结点,两个long long占16字节;

算一下是80多兆了,似乎实现上就爆掉了?所以这个思路不可行;

我们并不能对时间预处理然后二分,那在二分的过程中处理事件;

只维护一个普通的线段树,那么执行一次二分是O(qlogqlogm)的;

然后复杂度O(nq*logqlogm)这比暴力还挫的复杂度。。

当然不是这样!我们把所有的n一起二分!

每次二分事件区间[l,r],将线段树调整至mid处;

然后统计所有的国家是否满足它的要求;

如果满足,则将其扔到[l,mid]再二分,满足则扔到[mid+1,r];

l==r记录一下答案就好啦!

复杂度O((q+n)logqlogm)?大概就是这么个东西;

好久不写数据结构写写还有点小激动呢2333;


代码:

#include<stdio.h>#include<string.h>#include<algorithm>#define N 310000#define lson l,mid,no<<1#define rson mid+1,r,no<<1|1using namespace std;typedef long long ll;struct node{int no,need,head;}c[N];int next[N],to[N],ce;int L[N],R[N],a[N];int n,m,T;ll sum[N<<2],cov[N<<2];int ans[N];bool vis[N];void Pushup(int no){sum[no]=sum[no<<1]+sum[no<<1|1];}void Pushdown(int no,int len){if(cov[no]){cov[no<<1]+=cov[no];cov[no<<1|1]+=cov[no];sum[no<<1]+=cov[no]*(len-(len>>1));sum[no<<1|1]+=cov[no]*(len>>1);cov[no]=0;}}void update(int l,int r,int no,int st,int en,int val){if(st<=l&&r<=en){cov[no]+=val;sum[no]+=(ll)val*(r-l+1);}else{Pushdown(no,r-l+1);int mid=l+r>>1;if(en<=mid)update(lson,st,en,val);else if(st>mid)update(rson,st,en,val);elseupdate(lson,st,en,val),update(rson,st,en,val);Pushup(no);}}ll query(int l,int r,int no,int x){if(l==r)return sum[no];else{Pushdown(no,r-l+1);int mid=l+r>>1;if(x<=mid)return query(lson,x);elsereturn query(rson,x);}}void add(int x,int y){to[++ce]=y;next[ce]=c[x].head;c[x].head=ce;}void slove(int l,int r,int st,int en){if(st>en)return ;if(l==r){for(int i=st;i<=en;i++)ans[c[i].no]=l;return ;}int mid=l+r>>1;while(mid>T){if(L[T+1]<=R[T+1])update(1,m,1,L[T+1],R[T+1],a[T+1]);elseupdate(1,m,1,L[T+1],m,a[T+1]),update(1,m,1,1,R[T+1],a[T+1]);T++;}while(mid<T){if(L[T]<=R[T])update(1,m,1,L[T],R[T],-a[T]);elseupdate(1,m,1,L[T],m,-a[T]),update(1,m,1,1,R[T],-a[T]);T--;}int i,j,cnt;ll temp;for(i=st,cnt=0;i<=en;i++){for(j=c[i].head,temp=0;j;j=next[j]){temp+=query(1,m,1,to[j]);if(temp>=c[i].need)break;}if(temp>=c[i].need)vis[i]=1,cnt++;elsevis[i]=0;}for(i=st,j=st;i<=en;i++){if(vis[i])swap(c[i],c[j++]);}slove(l,mid,st,st+cnt-1);slove(mid+1,r,st+cnt,en);}int main(){int q,i,j,k,x,y;scanf("%d%d",&n,&m);for(i=1;i<=m;i++)scanf("%d",&x),add(x,i);for(i=1;i<=n;i++)scanf("%d",&c[i].need),c[i].no=i;scanf("%d",&q);for(i=1;i<=q;i++)scanf("%d%d%d",L+i,R+i,a+i);q++;L[q]=1,R[q]=m,a[q]=1e9;slove(1,q,1,n);for(i=1;i<=n;i++)if(ans[i]!=q)printf("%d\n",ans[i]);elseputs("NIE");return 0;}



0 0
原创粉丝点击