zoukankan      html  css  js  c++  java
  • suoi44 核能显示屏 (cdq分治)

    首先二维树状数组肯定开不下

    仿照二维树状数组的做法,如果有差分数组$d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1]$,那么就有:

    $$sum[x][y]=sumlimits_{i=1}^{x}{sumlimits_{j=1}^{y}{sumlimits_{k=1}^{i}{sumlimits_{l=1}^{j}{d[k][l]}}}}$$

    $$=sumlimits_{i=1}^{x}{sumlimits_{k=1}^{i}{sumlimits_{j=1}^{y}{((y+1)d[k][j]-j*d[k][j])}}}$$

    $$=sumlimits_{i=1}^{x}{sumlimits_{j=1}^{y}{(x+1)(y+1)d[i][j]-(x+1)*j*d[i][j]-(y+1)*i*d[i][j]+i*j*d[i][j]}}$$

    所以把询问拆成四个(前缀和)、修改拆成四个(差分))

    已经按时间排好序,然后把x作为第二维来cdq,开d,i*d,j*d,i*j*d四个树状数组统计答案就可以了

    上帝造题的七分钟也可以这样做,不过常数太大要吸氧

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define CLR(a,x) memset(a,x,sizeof(a))
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn=1e4+10,maxm=3e4+10;
     7 
     8 inline ll rd(){
     9     ll x=0;char c=getchar();int neg=1;
    10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    12     return x*neg;
    13 }
    14 
    15 struct Node{
    16     int t,x,y,o;ll v;
    17     Node(int a=0,int b=0,int c=0,int d=0,int e=0){
    18         t=a,x=b,y=c,v=d,o=e;
    19     }//o==1查 o==0改
    20 }op[maxm*4],tmp[maxm*4];
    21 ll dd[maxn],id[maxn],jd[maxn],ijd[maxn];
    22 ll ans[maxm];
    23 int N,M;
    24 bool isask[maxm];
    25 
    26 inline int lowbit(int x){return x&(-x);}
    27 inline void add(ll *t,int x,ll y){
    28     for(;x<=N;x+=lowbit(x)) t[x]+=y;
    29 }
    30 inline ll query(ll *t,int x){
    31     ll re=0;for(;x;x-=lowbit(x)) re+=t[x];return re;
    32 }
    33 
    34 void cdq(int l,int r){
    35     if(l==r) return;
    36     int m=l+r>>1;
    37     cdq(l,m);cdq(m+1,r);
    38     int p=l,q=m+1,n=0;
    39     for(;q<=r;q++){
    40         for(;p<=m&&op[p].x<=op[q].x;p++){
    41             tmp[++n]=op[p];
    42             if(op[p].o!=0) continue;
    43             add(dd,op[p].y,op[p].v);
    44             add(id,op[p].y,op[p].v*op[p].x);
    45             add(jd,op[p].y,op[p].v*op[p].y);
    46             add(ijd,op[p].y,op[p].v*op[p].x*op[p].y);
    47         }
    48         tmp[++n]=op[q];
    49         if(op[q].o!=1) continue;
    50         ll re=query(dd,op[q].y)*(op[q].x+1)*(op[q].y+1);
    51         re-=query(id,op[q].y)*(op[q].y+1);
    52         re-=query(jd,op[q].y)*(op[q].x+1);
    53         re+=query(ijd,op[q].y);
    54         ans[op[q].t]+=re*op[q].v;
    55     }for(;p<=m;p++) tmp[++n]=op[p];
    56     for(int p=l;p<=m&&op[p].x<=op[r].x;p++){
    57         if(op[p].o!=0) continue;
    58         add(dd,op[p].y,-op[p].v);
    59         add(id,op[p].y,-op[p].v*op[p].x);
    60         add(jd,op[p].y,-op[p].v*op[p].y);
    61         add(ijd,op[p].y,-op[p].v*op[p].x*op[p].y);
    62     }
    63     memcpy(op+l,tmp+1,sizeof(Node)*n);
    64 }
    65 
    66 int main(){
    67     //freopen("","r",stdin);
    68     int i,j;
    69     N=rd(),M=rd();
    70     for(i=1,j=0;i<=M;i++){
    71         int a=rd(),x1=rd(),y1=rd(),x2=rd(),y2=rd();
    72         if(!a){
    73             op[++j]=Node(i,x2,y2,1,1);
    74             if(x1>1&&y1>1) op[++j]=Node(i,x1-1,y1-1,1,1);
    75             if(x1>1) op[++j]=Node(i,x1-1,y2,-1,1);
    76             if(y1>1) op[++j]=Node(i,x2,y1-1,-1,1);
    77             isask[i]=1;
    78         }else{
    79             op[++j]=Node(i,x1,y1,a,0);
    80             if(x2<N&&y2<N) op[++j]=Node(i,x2+1,y2+1,a,0);
    81             if(y2<N) op[++j]=Node(i,x1,y2+1,-a,0);
    82             if(x2<N) op[++j]=Node(i,x2+1,y1,-a,0);
    83         }
    84     }
    85     cdq(1,j);
    86     for(i=1;i<=M;i++){
    87         if(isask[i]) printf("%lld
    ",ans[i]); 
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    面向对象并不是必要的
    linq 总结
    垃圾自动回收的一个方案
    随手记 手机软件的不足,和开发自己理财软件的想法
    以人的角度去解决问题
    浮点数比较
    集中原则——软件设计之道
    云在何方
    我遇到了DLL地狱
    在C#.net中如何操作XML
  • 原文地址:https://www.cnblogs.com/Ressed/p/9777876.html
Copyright © 2011-2022 走看看