zoukankan      html  css  js  c++  java
  • BZOJ2527 [Poi2011]Meteors 整体二分 树状数组

    原文链接http://www.cnblogs.com/zhouzhendong/p/8686460.html

    题目传送门 - BZOJ2527

    题意

      有$n$个国家。

      太空里有$m$个太空站排成一个圆圈。其中第$i$的太空站是第$O_i$个国家的。

      第$i$个国家要通过自己的太空站收集$P_i$数量的陨石雨。

      现在有$k$场陨石雨,第$i$场陨石雨会给$L_i~R_i$(顺时针数)的所有太空站分别带来$A_i$数量的陨石雨。

      再解释下这个$L_i~R_i$,如果$L_i<=R_i$,那么代表的区间是$L_i,L_i+1,...,R_i-1,R_i$;如果$L_i>R_i$,那么代表的区间是$L_i,L_i+1,m-1,m, 1,2,R_i-1,R_i$。

      现在对于每一个国家问至少要经过几次陨石雨才能收集到足够的陨石雨。如果$k$次之后都收集不够,那么输出$NIE$。

      $n,m,kleq 3 imes 10^5, P_i,A_ileq 10^9$

    题解

      整体二分基础题吧、、

      二分下要经历的陨石雨次数。

      树状数组实现区间修改和单点询问。

      然后好像说完了。

      整体二分的思路类似于这一题BZOJ3110

      具体看代码。

      我也是真悲催,题意看错好几次。

      煞笔错误好几个。QAQ

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=300005;
    int n,m,k,p[N],id[N],ans[N],Ltmp[N],Rtmp[N];
    vector <int> pos[N];
    LL tree[N];
    struct Rain{
    	int L,R,a;
    	void get(){
    		scanf("%d%d%d",&L,&R,&a);
    	}
    }rain[N];
    int lowbit(int x){
    	return x&-x;
    }
    void add(int x,LL y){
    	for (;x<=m;x+=lowbit(x))
    		tree[x]+=y;
    }
    LL sum(int x){
    	LL ans=0;
    	for (;x>0;x-=lowbit(x))
    		ans+=tree[x];
    	return ans;
    }
    void raining(int L,int R,LL v){
    	if (L<=R)
    		add(L,v),add(R+1,-v);
    	else
    		add(1,v),add(R+1,-v),add(L,v),add(m+1,-v);
    }
    void solve(int kL,int kR,int L,int R){
    	if (L>R)
    		return;
    	if (kL==kR){
    		for (int i=L;i<=R;i++)
    			ans[id[i]]=kL;
    		return;
    	}
    	int l=0,r=0,kmid=(kL+kR)>>1;
    	for (int i=kL;i<=kmid;i++)
    		raining(rain[i].L,rain[i].R,rain[i].a);
    	for (int i=L;i<=R;i++){
    		LL res=0;
    		for (int j=0;j<pos[id[i]].size();j++){
    			res+=sum(pos[id[i]][j]);
    			if (res>=p[id[i]])
    				break;
    		}
    		if (res>=p[id[i]])
    			Ltmp[++l]=id[i];
    		else
    			Rtmp[++r]=id[i],p[id[i]]-=res;
    	}
    	for (int i=kL;i<=kmid;i++)
    		raining(rain[i].L,rain[i].R,-rain[i].a);
    	for (int i=L;i<=L+l-1;i++)
    		id[i]=Ltmp[i-L+1];
    	for (int i=R-r+1;i<=R;i++)
    		id[i]=Rtmp[i-R+r];
    	solve(kL,kmid,L,L+l-1);
    	solve(kmid+1,kR,R-r+1,R);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		pos[i].clear();
    	for (int i=1,x;i<=m;i++)
    		scanf("%d",&x),pos[x].push_back(i);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&p[i]),id[i]=i;
    	scanf("%d",&k);
    	for (int i=1;i<=k;i++)
    		rain[i].get();
    	k++;
    	rain[k].L=1,rain[k].R=m,rain[k].a=1e9;
    	solve(1,k,1,n);
    	for (int i=1;i<=n;i++)
    		if (ans[i]<k)
    			printf("%d
    ",ans[i]);
    		else
    			puts("NIE");
    	return 0;
    }
    

      

  • 相关阅读:
    Ubuntu18.04可执行文件运行提示No such file or directory
    Linux gcc(ar命令)打包库到另一个库中的另外一种方法
    干干净净的grep
    C语言里面和时间有关的函数
    Ubuntu上安装tftp服务
    因为新冠,宅家2周,折腾了一下电视盒子。
    批量处理文件的Python程序
    Windows 10中使用VirtualBox
    重采样Resample 的一些研究记录。
    微信公众号接入第三方服务器,设置自动回复、关键回复、自定义菜单,配置及开发流程
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ2527.html
Copyright © 2011-2022 走看看