zoukankan      html  css  js  c++  java
  • 【BZOJ2683】简单题

    cdq分治妙啊

    (被改过题面的)原题:

    dydxh所出的题目是这样的:
    有一个N*N矩阵,给出一系列的修改和询问,修改是这样的:将(x,y)中的数字加上k,而询问是这样的:求(x1,y1)到(x2,y2)这个子矩阵内所有数字的和。
    虽然这么高级的数据结构题mzx这种菜逼当然不会,但是由于dydxh给mzx留了一条没有强制在线的生路,所以mzx决定挑战一下这道题。

    1<=N<=500000,操作数不超过200000个,操作1中的k为正整数,且不超过2000

    思路很妙,知道为什么要这样做但是感觉考场上想不出来QAQ

    首先询问容斥成4个前缀和问题,设时间轴为z,问题就变成询问z<qz,x<qx,y<qy里面的数总和是多少

    然后就跟数星星很像了,排序x,这样右边的x保证比左边的x大,cdq分治z,树状数组y

    看网上的做法和我之前想的有点不一样,我之前想的是想归并排序那样从将右边的队头和左边的队头比较,小的出队,先递归,再计算

    网上比较多的做法是,先计算,左边的修改给右边的查询贡献,然后把时间轴<=mid的放到mid左边,>mid的放到右边,再递归下一层

    感觉第二种对于我来说更好理解吧,比较贴合cdq分治的本质,现在还不能理解这两种写法的联系

    听闵神说递归的效率非常低?我和山神的递归2.2s,闵神迭代0.4s……

    还需要想一下迭代的写法啊

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<vector>
     8 using namespace std;
     9 int read(){int z=0,mark=1;  char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
    11     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    12     return z*mark;
    13 }
    14 struct cdd{int x,y,z,v,mk;}a[810000];  int tp=0;
    15 int n;
    16 int e[510000],lbt[510000];
    17 cdd q[810000];  int hd=0;
    18 int ans[210000];
    19 int t=0;
    20 void gtlbt(){for(int i=1;i<=500000;++i)lbt[i]=i&-i;}
    21 void mdf(int x,int y){while(x<=n)  e[x]+=y,x+=lbt[x];}
    22 int qr(int x){int bwl=0;  while(x)  bwl+=e[x],x-=lbt[x];  return bwl;}
    23 //int qr(int x){int bwl=0;  while(x)  bwl+=e[x],x-=lbt[x];}
    24 void dfs(int l,int r){
    25     if(l==r)  return ;
    26     int md=(l+r)>>1;
    27     for(int i=l;i<=r;++i){
    28         if(!a[i].mk && a[i].z<=md)  mdf(a[i].y,a[i].v);
    29         else if(a[i].mk && a[i].z>md) 
    30             ans[a[i].v]+=a[i].mk*qr(a[i].y);
    31     }
    32     for(int i=l;i<=r;++i)if(!a[i].mk && a[i].z<=md)  mdf(a[i].y,-a[i].v);
    33     int t1=l,t2=md+1;
    34     for(int i=l;i<=r;++i)  q[(a[i].z<=md?t1:t2)++]=a[i];
    35     for(int i=l;i<=r;++i)  a[i]=q[i];
    36     dfs(l,md),dfs(md+1,r);
    37 }
    38 bool cmp(cdd x,cdd y){return (x.x==y.x)?((x.z==y.z)?x.y<y.y:x.z<y.z):x.x<y.x;}
    39 int main(){//freopen("ddd.in","r",stdin);
    40     gtlbt();
    41     cin>>n;
    42     int mk,x,y,z,v;
    43     while((mk=read())!=3){
    44         if(mk==1)  a[++tp].mk=0,a[tp].x=read(),a[tp].y=read(),a[tp].v=read(),a[tp].z=tp;
    45         else{
    46             x=read(),y=read(),z=read(),v=read();
    47             a[++tp].mk=1,a[tp].x=z,a[tp].y=v,a[tp].z=tp,a[tp].v=++t;
    48             a[++tp].mk=1,a[tp].x=x-1,a[tp].y=y-1,a[tp].z=tp,a[tp].v=t;
    49             a[++tp].mk=-1,a[tp].x=z,a[tp].y=y-1,a[tp].z=tp,a[tp].v=t;
    50             a[++tp].mk=-1,a[tp].x=x-1,a[tp].y=v,a[tp].z=tp,a[tp].v=t;
    51         }
    52     }
    53     sort(a+1,a+tp+1,cmp);
    54     dfs(1,tp);
    55     for(int i=1;i<=t;++i)  printf("%d
    ",ans[i]);
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    [转载]Android之NetworkOnMainThreadException异常
    Android学习笔记(一): Fragment(一) 基本概念和生命周期
    ubuntu 64位系统创建android 项目找不到R文件
    Cocos2d之“引用计数”内存管理机制实现解析
    Cocos2d之Ref类与内存管理使用详解
    JSON之HelloWord
    Mysql之HelloWorld
    Linux inittab 配置文件
    计算机端口号对应服务总结
    perl文件读写
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6412232.html
Copyright © 2011-2022 走看看