zoukankan      html  css  js  c++  java
  • Ynoi2018 五彩斑斓的世界

    Link
    维护块内极差/最大值(mx),以及各个数出现的首地址(不一定是第一个),其它的用并查集并过去。
    对于修改,分为边角和整块考虑。
    边角的话我们把边角所在的块暴力修改并重构,单次复杂度是(O(sqrt n))的。
    整块的话我们有两个暴力做法:
    一是把(ge x)的数(k)暴力并到(k-x)上去,单次的复杂度是(O(mx-x))
    二是给整个块打一个(-x)的标记,然后把(<x)的数(k)暴力并到(k+x)上去,单次的复杂度是(O(x))
    我们把这两个暴力拼到一起,如果(mx<2x)就采用第一个暴力,否则采用第二个暴力。
    这样可以保证一个块内所有全体修改的总体复杂度不会超过(O(max a))
    查询的话直接整块直接查询边角暴力。
    注意到题目并没有要求强制在线,所以我们可以把所有操作离线下来,然后一个个块做,这样可以做到(O(n))空间。

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<cstdlib>
    #include<utility>
    #include<algorithm>
    #define fi first
    #define se second
    namespace IO
    {
        char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[11],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
        char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
        void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
        void Put(char x){*oS++=x;if(oS==oT)Flush();}
        int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
        void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('
    ');}
    }using namespace IO;
    using pi=std::pair<int,int>;
    const int N=500007;
    int n,m,B,a[N],b[N],f[N];pi v[N];
    struct node{int o,l,r,x,ans;}q[N];
    int find(int x){return x==f[x]? x:f[x]=find(f[x]);}
    void merge(int x,int y){v[y].fi? f[v[x].fi]=v[y].fi:b[v[y].fi=v[x].fi]=y,v[y].se+=v[x].se,v[x]={0,0};}
    #define update()							
        mx=0;								
        for(int k=L,x;k<=R;++k) mx=std::max(mx,x=a[k]),v[x].fi? f[k]=v[x].fi:(b[v[x].fi=f[k]=k]=x),++v[x].se;
    int main()
    {
        n=read(),m=read();int B=701+(rand()&7);
        for(int i=1;i<=n;++i) a[i]=read();
        for(int i=1;i<=m;++i) q[i]={read(),read(),read(),read()};
        for(int i=1;;++i)
        {
    	int L=i*B-B+1,R=std::min(n,i*B),mx,tag=0;
    	if(L>n) break;
    	memset(v,0,sizeof v),update();
    	for(int j=1;j<=m;++j)
    	{
    	    int l=q[j].l,r=q[j].r,x=q[j].x;
    	    if(r<L||R<l) continue;
    	    if(q[j].o==1)
    	    {
    		if(l<=L&&R<=r)
    		{
    		    if((x<<1)<=mx-tag)
    		    {
    			for(int k=tag+1;k<=tag+x;++k) if(v[k].fi) merge(k,k+x);
    			tag+=x;
    		    }
    		    else 
    		    {
    			for(int k=mx;k>tag+x;--k) if(v[k].fi) merge(k,k-x);
    			mx=std::min(mx,tag+x);
    		    }
    		}
    		else
    		{
    		    for(int k=L;k<=R;++k) a[k]=b[find(k)],v[a[k]]={0,0},a[k]-=tag;
    		    memset(b+L,0,(R-L+1)<<2),tag=0;l=std::max(l,L),r=std::min(r,R);
    		    for(int k=l;k<=r;++k) if(a[k]>x) a[k]-=x;
    		    update();
    		}
    	    }
    	    else
    	    {
    		if(l<=L&&R<=r) { if(x+tag<=500000) q[j].ans+=v[x+tag].se; }
    		else { l=std::max(l,L),r=std::min(r,R); for(int k=l;k<=r;++k) if(b[find(k)]==tag+x) ++q[j].ans;}
    	    }
    	}
        }
        for(int i=1;i<=m;++i) if(q[i].o==2) write(q[i].ans);  
        return Flush(),0;
    }
    
  • 相关阅读:
    1767:字符合并
    成绩单
    floj 2264
    floj 2265 【lxs Contest #141】航海舰队
    CF932D Tree
    1745:分组
    1744:跳台阶
    Xamarin.Forms之跨平台性能
    Xamarin.Forms之部署和测试(性能)
    Xamarin.Forms数据绑定
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12442541.html
Copyright © 2011-2022 走看看