zoukankan      html  css  js  c++  java
  • [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
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    SAP和ABAP内存的区别
    ABAP如何限制自己开发的耗时报表在sap系统中运行的个数,以保证正常业务的进行
    ABAP如何创建动态结构的报表
    FISAP财务成本知识库
    ABAPSAP显示处理进度的函数
    ABAP如何在REUSE_ALV_GRID_DISPLAY标识不同行用不同的颜色
    Java: 获取当前执行位置的文件名/类名/方法名/行号
    查询不重复的列
    [转载]用SQL语句添加删除修改字段
    [转载]查询之order by,group by和having的使用(一)
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/12041429.html
Copyright © 2011-2022 走看看