• 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;
    }
    

      

  • 相关阅读:
    Sqlserver日期函数应用
    SSRS匿名访问
    SSAS动态添加分区(一)
    BI就是报表?
    CreateEvent函数/多线程/c++
    字符编码介绍
    Win7 64下Visual C++ 6.0不兼容
    Winpcap安装,Cannot open include file 'pcap.h'
    PPT开发 * .pps 文件类型
    Visual Assist X 工具栏不显示 toolbar
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ2527.html
Copyright © 2020-2023  润新知