• 【带修莫队】【权值分块】bzoj3196 Tyvj 1730 二逼平衡树


    这题用了三种算法写:

    分块+二分:O(n*sqrt(n*log(n))

    函数式权值分块:O(n*sqrt(n))

    带修莫队+权值分块:O(n5/3)

    结果……复杂度越高的实际上跑得越快……最后这个竟然进第一页了……

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int f,C;
    inline void R(int &x){
        C=0;f=1;
        for(;C<'0'||C>'9';C=getchar())if(C=='-')f=-1;
        for(x=0;C>='0'&&C<='9';C=getchar())(x*=10)+=(C-'0');
        x*=f;
    }
    void P(int x){
        if(x<10)putchar(x+'0');
        else{P(x/10);putchar(x%10+'0');}
    }
    #define N 50001
    #define BN 320
    int n,m,c[N],a[N<<1],enc,enq,num2[N],ma[N<<1],anss[N],en,en2;
    struct Point{int v,p;}t[N<<1];
    bool operator < (const Point &a,const Point &b){return a.v<b.v;}
    struct ASK{int op,l,r,k,p,t;}Q[N];
    bool operator < (const ASK &a,const ASK &b)
    {
    	if(num2[a.l]==num2[b.l])
    	  {
    	  	if(num2[a.r]==num2[b.r])
    		  return a.t<b.t;
    		return num2[a.r]<num2[b.r];
    	  }
    	return num2[a.l]<num2[b.l];
    }
    struct UPT{int x,y,z;}CH[N];
    int l[BN],r[BN],num[N<<1],b[N<<1],sumv[BN];
    void makeblock()
    {
        int sz=sqrt(en2),sum=1; if(!sz) sz=1;
        for(;sum*sz<en2;sum++)
          {
            l[sum]=r[sum-1]+1;
            r[sum]=sz*sum;
            for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
          }
        l[sum]=r[sum-1]+1;
        r[sum]=en2;
        for(int i=l[sum];i<=r[sum];i++) num[i]=sum;
    }
    void Insert(const int &x){b[x]++; sumv[num[x]]++;}
    void Delete(const int &x){b[x]--; sumv[num[x]]--;}
    int Rank(const int &x)
    {
        int cnt=0;
        for(int i=1;i<num[x];i++) cnt+=sumv[i];
        for(int i=l[num[x]];i<x;i++) cnt+=b[i];
        return cnt+1;
    }
    int Kth(const int &x)
    {
        int cnt=0;
        for(int i=1;;i++)
          {
            cnt+=sumv[i];
            if(cnt>=x)
              {
                cnt-=sumv[i];
                for(int j=l[i];;j++)
                  {cnt+=b[j]; if(cnt>=x) return j;}
              }
          }
    }
    int Next(const int &x)
    {
        for(int i=x+1;i<=r[num[x]];i++) if(b[i]) return i;
        for(int i=num[x]+1;;i++) if(sumv[i])
          for(int j=l[i];;j++)
            if(b[j]) return j;
    }
    int Pre(const int &x)
    {
        for(int i=x-1;i>=l[num[x]];i--) if(b[i]) return i;
        for(int i=num[x]-1;;i--) if(sumv[i])
          for(int j=r[i];;j--)
            if(b[j]) return j;
    }
    void Query(const int &p)
    {
    	if(Q[p].op==1) anss[Q[p].p]=Rank(Q[p].k);
    	else if(Q[p].op==2) anss[Q[p].p]=ma[Kth(Q[p].k)];
    	else if(Q[p].op==4) anss[Q[p].p]=ma[Pre(Q[p].k)];
    	else if(Q[p].op==5) anss[Q[p].p]=ma[Next(Q[p].k)];
    }
    int op[N];
    int main()
    {
    	R(n); R(m);
    	int blo=0,sz=(int)pow((double)n,2.0/3.0);
    	if(!sz) sz=1;
    	for(int i=1;i<=n;++i)
    	  {
    	  	R(t[i].v); t[i].p=i;
    	  	if(i%sz==1||sz==1) ++blo;
    	  	num2[i]=blo;
    	  }
    	en=n;
    	for(int i=1;i<=m;++i)
    	  {
    	  	R(op[i]);
    	  	if(op[i]==1||op[i]==4||op[i]==5)
    	  	  {
    			++enq; ++en;
    	  		R(Q[enq].l); R(Q[enq].r);
    			Q[enq].p=enq; Q[enq].op=op[i]; Q[enq].t=enc;
    			R(t[en].v); t[en].p=en;
    		  }
    	  	else if(op[i]==2)
    	  	  {
    			++enq;
    			R(Q[enq].l); R(Q[enq].r); R(Q[enq].k);
    			Q[enq].p=enq; Q[enq].op=op[i]; Q[enq].t=enc;
    		  }
    	  	else
    	  	  {
    			++enc; ++en;
    			R(CH[enc].x); R(t[en].v);
    			t[en].p=en;
    		  }
    	  }
    	sort(t+1,t+en+1);
    	ma[a[t[1].p]=++en2]=t[1].v;
    	for(int i=2;i<=en;++i)
    	  {
    	  	if(t[i].v!=t[i-1].v) ++en2;
    	  	ma[a[t[i].p]=en2]=t[i].v;
    	  }
    	makeblock();
    	memcpy(c,a,(n+1)*sizeof(int));
    	en=n; enc=0; enq=0;
    	for(int i=1;i<=m;++i)
    	  {
    	  	if(op[i]==3)
    	  	  {
    	  	  	++en; ++enc;
    	  	  	CH[enc].y=a[en]; CH[enc].z=c[CH[enc].x];
    	  	  	c[CH[enc].x]=a[en];
    	  	  }
    	  	else
    	  	  {
    	  	  	++enq;
    	  		if(op[i]!=2) Q[enq].k=a[++en];
    	  	  }
    	  }
    	sort(Q+1,Q+enq+1);
    	for(int i=1;i<=Q[1].t;++i)
    	  a[CH[i].x]=CH[i].y;
    	for(int i=Q[1].l;i<=Q[1].r;++i) Insert(a[i]);
        Query(1);
        for(int i=2;i<=enq;++i)
          {
          	if(Q[i-1].t<Q[i].t) for(int j=Q[i-1].t+1;j<=Q[i].t;++j)
    	  	  {
    	  	  	if(CH[j].x>=Q[i-1].l&&CH[j].x<=Q[i-1].r)
    	  	  	  {
    	  	  	  	Insert(CH[j].y);
    	  	  	  	Delete(a[CH[j].x]);
    	  	  	  }
    	  	  	a[CH[j].x]=CH[j].y;
    	  	  }
    	  	else for(int j=Q[i-1].t;j>Q[i].t;--j)
    	  	  {
    	  	  	if(CH[j].x>=Q[i-1].l&&CH[j].x<=Q[i-1].r)
    	  	  	  {
    	  	  	  	Insert(CH[j].z);
    	  	  	  	Delete(a[CH[j].x]);
    	  	  	  }
    	  	  	a[CH[j].x]=CH[j].z;
    	  	  }
            if(Q[i].l<Q[i-1].l) for(int j=Q[i-1].l-1;j>=Q[i].l;--j) Insert(a[j]);
            else for(int j=Q[i-1].l;j<Q[i].l;++j) Delete(a[j]);
            if(Q[i].r<Q[i-1].r) for(int j=Q[i-1].r;j>Q[i].r;--j) Delete(a[j]);
            else for(int j=Q[i-1].r+1;j<=Q[i].r;++j) Insert(a[j]);
            Query(i);
          }
        for(int i=1;i<=enq;++i) P(anss[i]),puts("");
    	return 0;
    }
  • 相关阅读:
    分享15款为jQuery Mobile定制的插件
    显​示​器​分​辨​率​调​高​后​黑​屏​的​最​佳​解​决​办​法
    out 和 ref 之间的区别整理
    赋值操作符重载
    最长公共子串
    最长递增子序列
    动态规划
    Eclipse支持Jquery代码提示(JqeuryWTP)
    ubuntu10.04编译内核不显示grub菜单解决
    CSS水平导航条和纵向导航条
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4326015.html
Copyright © 2020-2023  润新知