• BZOJ2874 : 训练士兵


    设$a[i][j]$表示$(i,j)$右下角要增加多少

    $aj[i][j]=a[i][j] imes j$

    $ai[i][j]=a[i][j] imes i$

    $aij[i][j]=a[i][j] imes i imes j$

    则查询$(x,y)$左上角内的权值和时,

    答案$=(x+1)(y+1)ask_{a}(x,y)-(x+1)ask_{aj}(x,y)-(y+1)ask_{ai}(x,y)+ask_{aij}(x,y)$。

    首先将坐标离散化,将修改拆成4个单点修改,然后从左往右插入点,用可持久化线段树维护二维前缀和。

    查询时拆成4次二维前缀和查询即可。

    时间复杂度$O((k+q)log k)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=80010,M=3000000;
    int n,m,k,q,i,j,x,y,X1,X2,Y1,Y2,s,cnt,bx[N],by[N],cl,g[N],nxt[N<<1];ll ans;
    struct P{int x,y,z;P(){}P(int _x,int _y,int _z){x=_x,y=_y,z=_z;}}a[N<<1];
    int tot,T[N],l[M],r[M];
    struct V{
      ll o,j,i,ij;
      V(){o=j=i=ij=0;}
      V(ll _o,ll _j,ll _i,ll _ij){o=_o,j=_j,i=_i,ij=_ij;}
      V(int x,int y,int z){o=z,j=1LL*z*y,i=1LL*z*x,ij=1LL*z*x*y;}
      inline V operator+(const V&b){return V(o+b.o,j+b.j,i+b.i,ij+b.ij);}
    }v[M],p;
    inline int lowerx(int x){
      int l=1,r=cl,mid,t=0;
      while(l<=r)if(bx[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    inline int lowery(int x){
      int l=1,r=cl,mid,t=0;
      while(l<=r)if(by[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
      return t;
    }
    int ins(int x,int a,int b,int c){
      int y=++tot;
      v[y]=v[x]+p;
      if(a==b)return y;
      int mid=(a+b)>>1;
      if(c<=mid)l[y]=ins(l[x],a,mid,c),r[y]=r[x];else l[y]=l[x],r[y]=ins(r[x],mid+1,b,c);
      return y;
    }
    ll asko(int x,int a,int b,int d){
      if(!x||!d)return 0;
      if(b<=d)return v[x].o;
      int mid=(a+b)>>1;
      ll t=asko(l[x],a,mid,d);
      if(d>mid)t+=asko(r[x],mid+1,b,d);
      return t;
    }
    ll askj(int x,int a,int b,int d){
      if(!x||!d)return 0;
      if(b<=d)return v[x].j;
      int mid=(a+b)>>1;
      ll t=askj(l[x],a,mid,d);
      if(d>mid)t+=askj(r[x],mid+1,b,d);
      return t;
    }
    ll aski(int x,int a,int b,int d){
      if(!x||!d)return 0;
      if(b<=d)return v[x].i;
      int mid=(a+b)>>1;
      ll t=aski(l[x],a,mid,d);
      if(d>mid)t+=aski(r[x],mid+1,b,d);
      return t;
    }
    ll askij(int x,int a,int b,int d){
      if(!x||!d)return 0;
      if(b<=d)return v[x].ij;
      int mid=(a+b)>>1;
      ll t=askij(l[x],a,mid,d);
      if(d>mid)t+=askij(r[x],mid+1,b,d);
      return t;
    }
    inline ll sum(int x,int y){
      int i=lowerx(x),j=lowery(y);
      return asko(T[i],1,cl,j)*(x+1)*(y+1)-askj(T[i],1,cl,j)*(x+1)-aski(T[i],1,cl,j)*(y+1)+askij(T[i],1,cl,j);
    }
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    int main(){
      read(n),read(m),read(k),read(q);
      while(k--){
        read(X1),read(X2),read(Y1),read(Y2),read(s);
        a[++cnt]=P(X1,Y1,s);
        a[++cnt]=P(X2+1,Y1,-s);
        a[++cnt]=P(X1,Y2+1,-s);
        a[++cnt]=P(X2+1,Y2+1,s);
        bx[++cl]=X1,by[cl]=Y1,bx[++cl]=X2+1,by[cl]=Y2+1;
      }
      sort(bx+1,bx+cl+1),sort(by+1,by+cl+1);
      for(i=1;i<=cnt;i++)nxt[i]=g[a[i].x=lowerx(a[i].x)],g[a[i].x]=i;
      for(i=1;i<=cl;i++)for(T[i]=T[i-1],j=g[i];j;j=nxt[j])p=V(bx[i],a[j].y,a[j].z),T[i]=ins(T[i],1,cl,lowery(a[j].y));
      while(q--){
        read(x),read(y);
        X1=ans%n+1,X2=(ans+x)%n+1;if(X1>X2)swap(X1,X2);
        Y1=ans%m+1,Y2=(ans+y)%m+1;if(Y1>Y2)swap(Y1,Y2);
        printf("%lld
    ",ans=sum(X2,Y2)-sum(X1-1,Y2)-sum(X2,Y1-1)+sum(X1-1,Y1-1));
      }
      return 0;
    }
    

      

  • 相关阅读:
    【转】i18n实现前端国际化(实例)
    【转】SQL Pretty Printer for SSMS 很不错的SQL格式化插件
    windows server IIS启用Windows authentication
    【转】命令行下载各种网上各种视频
    解决python “No module named pip”
    【转】excel音标乱码
    【转】自动化部署之jenkins及简介
    【转】右键菜单管理
    【转】C# @作用
    【转】NGen
  • 原文地址:https://www.cnblogs.com/clrs97/p/4856632.html
Copyright © 2020-2023  润新知