zoukankan      html  css  js  c++  java
  • bzoj2683简单题

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <algorithm>
     5 #include <cstring>
     6 #define maxn 500005
     7 #define maxm 800005 
     8 using namespace std;
     9 
    10 int n,m,cnt,sum[maxn],pos[maxm],ans[maxm];
    11 struct date{
    12     int op,x,y,v,id;
    13 }qs[maxm];
    14 
    15 bool comp(date x,date y){
    16     return x.x<y.x;
    17 }
    18 
    19 int lowbit(int x){
    20     return x&(-x);
    21 }
    22 
    23 void add(int x,int y){
    24     for (int i=x;i<=n;i+=lowbit(i)){
    25         sum[i]+=y;
    26     }
    27 }
    28 
    29 int  query(int x){
    30     int temp=0;
    31     for (int i=x;i>0;i-=lowbit(i)){
    32         temp+=sum[i];
    33     }
    34     return temp;
    35 }
    36 
    37 void cdq_solve(int l,int r){
    38     if (l==r) return;
    39     int mid=(l+r)/2,temp=0;
    40     cdq_solve(l,mid),cdq_solve(mid+1,r);
    41     sort(qs+l,qs+mid+1,comp),sort(qs+mid+1,qs+r+1,comp);
    42     int i=l,j=mid+1;
    43     while (j<=r){
    44         while (qs[i].op==2&&i<=mid) i++;
    45         while (qs[j].op==1&&j<=r) j++;
    46         if (i<=mid&&qs[i].x<=qs[j].x) add(qs[i].y,qs[i].v),i++,temp=i-1;
    47         else if (j<=r) ans[qs[j].id]+=query(qs[j].y),j++;
    48     }
    49     for (int t=l;t<=temp;t++) if (qs[t].op==1) add(qs[t].y,-qs[t].v); 
    50 }
    51 
    52 int main(){
    53     memset(ans,0,sizeof(ans));
    54     memset(sum,0,sizeof(sum));
    55     int op,x1,x2,y1,y2;
    56     scanf("%d",&n),m=cnt=0;
    57     for (;;){
    58         scanf("%d",&op);
    59         if (op==1){
    60             qs[++m].op=op,qs[m].id=m;
    61             scanf("%d%d%d",&qs[m].x,&qs[m].y,&qs[m].v);
    62         }else{
    63             if (op==2){
    64                 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    65                 pos[++cnt]=m;
    66                 qs[++m].op=op,qs[m].x=x1-1,qs[m].y=y1-1,qs[m].id=m;
    67                 qs[++m].op=op,qs[m].x=x2,qs[m].y=y2,qs[m].id=m;        
    68                 qs[++m].op=op,qs[m].x=x1-1,qs[m].y=y2,qs[m].id=m;
    69                 qs[++m].op=op,qs[m].x=x2,qs[m].y=y1-1,qs[m].id=m;
    70             }else break;
    71         }
    72     }
    73     cdq_solve(1,m);
    74     for (int i=1;i<=cnt;i++) printf("%d
    ",ans[pos[i]+1]+ans[pos[i]+2]-ans[pos[i]+3]-ans[pos[i]+4]);
    75 }
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2683

    题目大意:给定一个n*n的矩形,以及若干个操作,操作有如下两种:

    1.给矩形的(x,y)加上一个v;

    2.询问某个子矩阵的权值和。

    数据范围:n<=5*10^5,操作数<=2*10^5;

    初看这题,尼玛这不是二维树状数组(二维线段树也行,不过是作死)傻逼题吗,期望复杂度O(nlog^2 n),空间复杂度n^2,再一看数据范围,GG。

    在ls神犇的教导下,我学会了四种通过此题的方法:1.二维线段树动态开点,空间复杂度nlog^2 n),有点卡空间。

    2.二维树状数组+hash表,可惜我没掌握这种正确姿势-.-;

    3.线段树套平衡树,线段树维护x坐标,每一层套一个splay,以y坐标为关键字,对于一个询问,拆成四个矩阵,再在对应的线段树中在splay中去找,更新答案即可,据说这种写法空间复杂度只有O(n)的复杂度,可以过。

    4.进入正题吧,这题的最佳姿势是cdq分治+树状数组维护区间和;

    前三种做法略过(在线做法),说说第四种做法(离线做法)吧:

    我先来说说cdq_分治的流程吧,cdq分治一般是解决具有一下两种性质的问题(只有修改和查询操作):

    1.只能用离线做法。

    2.每个修改操作对询问的影响是独立的,即与之前的修改操作无关。

    cdq分治与一般的分治不同,一般的分治分出来的子区间是独立的,个个击破即可,而cdq分治分出来的两个子区间是相互联系的。(以下的分治都是指cdq分治)

    由于在该问题中,每个询问只与在此之前的修改操作有关。

    对于区间l,mid,记为区间1,区间mid+1,r,记为区间2,

    过程:

    1.递归处理区间(1),

    2.递归处理区间(2),

    3.统计区间1中的修改操作对区间2中的询问操作的影响。

    4.算法结束。

    关键在于第3步,对于这个题,我们将两个区间各自按x坐标排序,然后用两个指针分别去扫一遍,遇到区间1中的修改操作,就把纵坐标加入树状数组,然后及时统计区间2中询问的答案即可。具体细节可见代码。

    cdq分治+树状数组

  • 相关阅读:
    Tensorflow中张量的数学运算
    TensorFlow2.0中tf.concat和tf.stack的区别
    机器学习之K-Means(聚类分析)
    机器学习之线性回归
    机器学习之随机森林
    机器学习之决策树
    python爬取FTP文件,并批量下载到本地。
    ATOM系列之-atom报错"Cannot load the system dictionary for zh-CN"
    开机出现loading (hd0)/ntldr。。。
    如何制作一张符合上传的照片
  • 原文地址:https://www.cnblogs.com/OYzx/p/5506468.html
Copyright © 2011-2022 走看看