zoukankan      html  css  js  c++  java
  • tyvj P1716

    P1716 - 上帝造题的七分钟

    From Riatre    Normal (OI)
    总时限:50s    内存限制:128MB    代码长度限制:64KB

    背景 Background

    裸体就意味着身体。

    描述 Description

    “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵。
    第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作。
    第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作。
    第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围。
    第五分钟,和雪说,要有耐心,于是便有了时间限制。
    第六分钟,吃钢琴男说,要省点事,于是便有了保证运算过程中及最终结果均不超过32位有符号整数类型的表示范围的限制。
    第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”
    ——《上帝造裸题的七分钟》
    所以这个神圣的任务就交给你了。

    输入格式 InputFormat

    输入数据的第一行为X n m,代表矩阵大小为n×m。
    从输入数据的第二行开始到文件尾的每一行会出现以下两种操作:
        L a b c d delta —— 代表将(a,b),(c,d)为顶点的矩形区域内的所有数字加上delta。
        k a b c d     —— 代表求(a,b),(c,d)为顶点的矩形区域内所有数字的和。

    请注意,k为小写。

    输出格式 OutputFormat

    针对每个k操作,在单独的一行输出答案。

    样例输入 SampleInput [复制数据]

    X 4 4
    L 1 1 3 3 2
    L 2 2 4 4 1
    k 2 2 3 3

    样例输出 SampleOutput [复制数据]

    12

    数据范围和注释 Hint

    对于10%的数据,1 ≤ n ≤ 16, 1 ≤ m ≤ 16, 操作不超过200个.
    对于60%的数据,1 ≤ n ≤ 512, 1 ≤ m ≤ 512.
    对于100%的数据,1 ≤ n ≤ 2048, 1 ≤ m ≤ 2048, 1 ≤ delta ≤ 500,操作不超过200000个,保证运算过程中及最终结果均不超过32位带符号整数类型的表示范围。

    来源 Source

    by XLk
    状态
    Accepted
    题号 P1716
    类型(?) 高级数据结构
    通过 99人
    提交 392次
    通过率 25%
      热烈庆祝AC200~~
      这道题被hja坑去写二维线段树,结果不是TLE就是MLE,正确的做法是二维树状数组区间修改与区间查询,在网上找得到详细解法。
    大体思路为维护a[][]使得前缀和sum[x][y]=segma(num[i][j])=segma(a[i][j]*(x-i+1)*(y-j+1))=segma(a[i][j]*(x+1)*(y+1)-(i+j)*a[i][j])
    =segma(a[i][j])*(x+1)*(y+1)+segma(i*j*a[i][j])-segma(j*a[i][j])*(x+1)-segma(i*a[i][j])*(y+1)
    最后,可以用4个树状数组分别维护上式中segma中引用部分。
      下面贴上两种解法代码
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 #define MAXN 2050
     7 #define MAXT 5000000
     8 typedef int tree_t[MAXN][MAXN];
     9 tree_t tree1,tree2,tree3,tree4;
    10 int lowbit(int x)
    11 {
    12         return x&(-x);
    13 }
    14 void add_val(tree_t tree,int x,int y,int v)
    15 {
    16 //        cout<<"ADD"<<x<<" "<<y<<" "<<v<<endl;
    17         int i,j;
    18         for (i=x;i<MAXN;i+=lowbit(i))
    19         {
    20                 for (j=y;j<MAXN;j+=lowbit(j))
    21                 {
    22                         tree[i][j]+=v;
    23                 }
    24         }
    25 }
    26 int query_sum(tree_t tree,int x,int y)
    27 {
    28         int i,j;
    29         int ret=0;
    30         for (i=x;i;i-=lowbit(i))
    31         {
    32                 for (j=y;j;j-=lowbit(j))
    33                 {
    34                         ret+=tree[i][j];
    35                 }
    36         }
    37         return ret;
    38 }
    39 //sum(x,y)=segma(a[i][j]*(x-i+1)*(y-j+1))
    40 //          =segma(a[i][j]*(x+1)*(y+1)-(i+j)*a[i][j]);
    41 //          =segma(a[i][j])*(x+1)*(y+1)-segma((i+j)*a[i][j])
    42 //
    43 void add_matrix(int xl,int yl,int xr,int yr,int v)
    44 {
    45         add_val(tree1,xr+1,yr+1,v);
    46         add_val(tree1,xl,yl,v);
    47         add_val(tree1,xl,yr+1,-v);
    48         add_val(tree1,xr+1,yl,-v);
    49         add_val(tree2,xr+1,yr+1,v*(xr+1)*(yr+1));
    50         add_val(tree2,xl,yl,v*(xl+0)*(yl+0));
    51         add_val(tree2,xl,yr+1,-v*(xl+0)*(yr+1));
    52         add_val(tree2,xr+1,yl,-v*(yl+0)*(xr+1));
    53         
    54         add_val(tree3,xr+1,yr+1,v*(xr+1));
    55         add_val(tree3,xl,yl,v*(xl+0));
    56         add_val(tree3,xl,yr+1,-v*(xl+0));
    57         add_val(tree3,xr+1,yl,-v*(xr+1));
    58 
    59         add_val(tree4,xr+1,yr+1,v*(yr+1));
    60         add_val(tree4,xl,yl,v*(yl+0));
    61         add_val(tree4,xl,yr+1,-v*(yr+1));
    62         add_val(tree4,xr+1,yl,-v*(yl+0));
    63 
    64 }    
    65 int query_matrix(int x,int y)
    66 {
    67         if (!x || !y)return 0;
    68         int ret=0;
    69         int t;
    70         ret+=query_sum(tree1,x,y)*(x+1)*(y+1);
    71         ret-=(t=query_sum(tree3,x,y))*(y+1);
    72         ret-=query_sum(tree4,x,y)*(x+1);
    73         ret+=query_sum(tree2,x,y);
    74         return ret;
    75 }
    76 int main()
    77 {
    78         freopen("input.txt","r",stdin);
    79         int i,j,k;
    80         int n,m;
    81         int x,y,z;
    82         char opt;
    83         scanf("%c%d%d
    ",&opt,&n,&m);
    84         int a,b,c,d,e;
    85         while (~scanf("%c",&opt))
    86         {
    87                 if (opt=='L')
    88                 {
    89                         scanf("%d%d%d%d%d
    ",&a,&b,&c,&d,&e);
    90                         add_matrix(a,b,c,d,e);
    91                 }else
    92                 {
    93                         scanf("%d%d%d%d
    ",&a,&b,&c,&d);
    94                         printf("%d
    ",query_matrix(a-1,b-1)+query_matrix(c,d)
    95                                         -query_matrix(a-1,d)-query_matrix(c,b-1));
    96                 }
    97         }
    98 }
    树状数组解法
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 #define MAXN 2050
      7 #define MAXT 2000000
      8 #define midx ((tree[now].lx+tree[now].rx)>>1)
      9 #define midy ((tree[now].ly+tree[now].ry)>>1)
     10 #define tnly tree[now].ly
     11 #define tnry tree[now].ry
     12 #define tnlx tree[now].lx
     13 #define tnrx tree[now].rx
     14 #define tnlazy tree[now].lazy
     15 #define area(t) ((tree[t].rx-tree[t].lx+1)*(tree[t].ry-tree[t].ly+1))
     16 struct node
     17 {
     18         int ch[2][2];
     19         int lx,rx,ly,ry;
     20         int sum;
     21         int lazy=0;
     22 }tree[MAXT];
     23 int root=0,topt=0;
     24 void new_node(int &now,int lx,int rx,int ly,int ry)
     25 {
     26         if (lx>rx ||ly>ry)return ;
     27         now=++topt;
     28         tnlx=lx;
     29         tnrx=rx;
     30         tnly=ly;
     31         tnry=ry;
     32 }
     33 
     34 void down(int now)
     35 {
     36         if (!tree[now].ch[0][0])
     37                 new_node(tree[now].ch[0][0],tnlx,midx,tnly,midy);
     38         if (!tree[now].ch[0][1] && tnly<tnry)
     39                 new_node(tree[now].ch[0][1],tnlx,midx,midy+1,tnry);
     40         if (!tree[now].ch[1][0] && tnlx<tnrx)
     41                 new_node(tree[now].ch[1][0],midx+1,tnrx,tnly,midy);
     42         if (!tree[now].ch[1][1] && tnly<tnry && tnlx<tnrx)
     43                 new_node(tree[now].ch[1][1],midx+1,tnrx,midy+1,tnry);
     44         if (tnlazy)
     45         {
     46                 tree[tree[now].ch[0][0]].sum+=tnlazy*area(tree[now].ch[0][0]);
     47                 tree[tree[now].ch[0][0]].lazy+=tnlazy;
     48                 if (tnlx<tnrx)
     49                 {
     50                         tree[tree[now].ch[1][0]].sum+=tnlazy*area(tree[now].ch[1][0]);
     51                         tree[tree[now].ch[1][0]].lazy+=tnlazy;
     52                 }
     53                 if (tnly<tnry)
     54                 {
     55                         tree[tree[now].ch[0][1]].sum+=tnlazy*area(tree[now].ch[0][1]);
     56                         tree[tree[now].ch[0][1]].lazy+=tnlazy;
     57                 }
     58                 if (tnlx<tnrx && tnly<tnry)
     59                 {
     60                         tree[tree[now].ch[1][1]].sum+=tnlazy*area(tree[now].ch[1][1]);
     61                         tree[tree[now].ch[1][1]].lazy+=tnlazy;
     62                 }
     63                 tnlazy=0;
     64         }
     65 }
     66 void up(int now)
     67 {
     68         tree[now].sum=0;
     69         tree[now].sum+=tree[tree[now].ch[0][0]].sum;
     70         tree[now].sum+=tree[tree[now].ch[1][0]].sum;
     71         tree[now].sum+=tree[tree[now].ch[0][1]].sum;
     72         tree[now].sum+=tree[tree[now].ch[1][1]].sum;
     73 }
     74 void add_val(int &now,int lx,int rx,int ly,int ry,int v)
     75 {
     76         if (tnlx==lx &&tnly==ly && tnrx==rx &&tnry==ry)
     77         {
     78                 tree[now].sum+=v*(rx-lx+1)*(ry-ly+1);
     79                 tree[now].lazy+=v;
     80                 return ;
     81         }
     82         down(now);
     83         if (rx<=midx && ry<=midy)
     84         {
     85                 add_val(tree[now].ch[0][0],lx,rx,ly,ry,v);
     86                 up(now);
     87                 return ;
     88         }
     89         if (rx<=midx && ly> midy)
     90         {
     91                 add_val(tree[now].ch[0][1],lx,rx,ly,ry,v);
     92                 up(now);
     93                 return ;
     94         }
     95         if (lx> midx && ry<=midy)
     96         {
     97                 add_val(tree[now].ch[1][0],lx,rx,ly,ry,v);
     98                 up(now);
     99                 return ;
    100         }
    101         if (lx> midx && ly> midy)
    102         {
    103                 add_val(tree[now].ch[1][1],lx,rx,ly,ry,v);
    104                 up(now);
    105                 return ;
    106         }
    107         if (rx<=midx)
    108         {
    109                 add_val(tree[now].ch[0][0],lx,rx,ly,midy,v);
    110                 add_val(tree[now].ch[0][1],lx,rx,midy+1,ry,v);
    111                 up(now);
    112                 return ;
    113         }
    114         if (lx> midx)
    115         {
    116                 add_val(tree[now].ch[1][0],lx,rx,ly,midy,v);
    117                 add_val(tree[now].ch[1][1],lx,rx,midy+1,ry,v);
    118                 up(now);
    119                 return ;
    120         }
    121         if (ry<=midy)
    122         {
    123                 add_val(tree[now].ch[0][0],lx,midx,ly,ry,v);
    124                 add_val(tree[now].ch[1][0],midx+1,rx,ly,ry,v);
    125                 up(now);
    126                 return ;
    127         }
    128         if (ly> midy)
    129         {
    130                 add_val(tree[now].ch[0][1],lx,midx,ly,ry,v);
    131                 add_val(tree[now].ch[1][1],midx+1,rx,ly,ry,v);
    132                 up(now);
    133                 return ;
    134         }
    135         add_val(tree[now].ch[0][0],lx,midx,ly,midy,v);
    136         add_val(tree[now].ch[0][1],lx,midx,midy+1,ry,v);
    137         add_val(tree[now].ch[1][0],midx+1,rx,ly,midy,v);
    138         add_val(tree[now].ch[1][1],midx+1,rx,midy+1,ry,v);
    139         up(now);
    140         return ;
    141 }
    142 int query(int now,int lx,int rx,int ly,int ry)
    143 {
    144         if (tree[now].lx==lx && tree[now].rx==rx &&
    145                         tree[now].ly==ly && tree[now].ry==ry)
    146         {
    147                 return tree[now].sum;
    148         }    
    149         down(now);
    150         int ans=0;
    151         if (rx<=midx && ry<=midy)
    152         {
    153                 ans=query(tree[now].ch[0][0],lx,rx,ly,ry);
    154                 return ans;
    155         }
    156         if (rx<=midx && ly> midy)
    157         {
    158                 ans=query(tree[now].ch[0][1],lx,rx,ly,ry);
    159                 return ans;
    160         }
    161         if (lx> midx && ry<=midy)
    162         {
    163                 ans=query(tree[now].ch[1][0],lx,rx,ly,ry);
    164                 return ans;
    165         }
    166         if (lx> midx && ly> midy)
    167         {
    168                 ans=query(tree[now].ch[1][1],lx,rx,ly,ry);
    169                 return ans;
    170         }
    171         if (rx<=midx)
    172         {
    173                 ans=query(tree[now].ch[0][0],lx,rx,ly,midy);
    174                 ans+=query(tree[now].ch[0][1],lx,rx,midy+1,ry);
    175                 return ans;
    176         }
    177         if (lx> midx)
    178         {
    179                 ans=query(tree[now].ch[1][0],lx,rx,ly,midy);
    180                 ans+=query(tree[now].ch[1][1],lx,rx,midy+1,ry);
    181                 return ans;
    182         }
    183         if (ry<=midy)
    184         {
    185                 ans=query(tree[now].ch[0][0],lx,midx,ly,ry);
    186                 ans+=query(tree[now].ch[1][0],midx+1,rx,ly,ry);
    187                 return ans;
    188         }
    189         if (ly> midy)
    190         {
    191                 ans=query(tree[now].ch[0][1],lx,midx,ly,ry);
    192                 ans+=query(tree[now].ch[1][1],midx+1,rx,ly,ry);
    193                 return ans;
    194         }
    195         ans=query(tree[now].ch[0][0],lx,midx,ly,midy);
    196         ans+=query(tree[now].ch[0][1],lx,midx,midy+1,ry);
    197         ans+=query(tree[now].ch[1][0],midx+1,rx,ly,midy);
    198         ans+=query(tree[now].ch[1][1],midx+1,rx,midy+1,ry);
    199         up(now);
    200         return ans;
    201 }
    202 int main()
    203 {
    204         //freopen("input.txt","r",stdin);
    205         int i,j,k;
    206         int n,m;
    207         int x,y,z;
    208         char opt;
    209         scanf("%c%d%d
    ",&opt,&n,&m);
    210         tree[1].lx=1;tree[1].rx=n;
    211         tree[1].ly=1;tree[1].ry=m;
    212         tree[1].sum=tree[1].lazy=0;
    213         topt=1;
    214         root=1;
    215         int a,b,c,d,e;
    216         while (~scanf("%s",&opt))
    217         {
    218                 if (opt=='L')
    219                 {
    220                         scanf("%d%d%d%d%d
    ",&a,&b,&c,&d,&e);
    221                         add_val(root,a,c,b,d,e);
    222                 }else
    223                 {
    224                         scanf("%d%d%d%d
    ",&a,&b,&c,&d);
    225                         printf("%d
    ",query(root,a,c,b,d));
    226                 }
    227         }
    228 
    229 }
    二维线段书解法
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    Java中Volatile关键字详解
    java hashmap&concurrentHashmap源理
    java CAS和AQS
    jvm内存模型
    springAop源码分析
    一个项目设置两个git地址,并最终实现一次性同时推送到到两个git地址上的方法总结
    H5实现横向滚动的方法总结
    tab吸顶的神奇-- css粘性属性
    H5制作显示轮播图的方法Swiper
    微信H5中禁止分享好友及分享到朋友圈的方法
  • 原文地址:https://www.cnblogs.com/mhy12345/p/3956911.html
Copyright © 2011-2022 走看看