zoukankan      html  css  js  c++  java
  • bzoj 1176 Mokia(CDQ分治,BIT)

      

    【题目链接】

      http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974

    【题意】

        定义查询操作与修改操作:1 x y z 为将格子(x,y)修改为z;2 x1 y1 x2 y2为查询以(x1,y1)为左上(x2,y2)为右下的子矩阵之和。

    【思路】

        cdq分治。

        矩阵初始值都为s,所以先不考虑。

        首先明确每一个修改操作都互不影响。然后把每一个对子矩阵的询问操作差分为对四个点的“前缀和”操作。

        先把所有的操作按照x升序排列。进行cdq分治。

        定义solve(l,r)为解决查询顺序在l,r区间内的操作,且在solve结束后保证区间按照x的递增排列。

      1) 将区间按照查询先后顺序重排

      2) Solve(l,mid)

      3) 计算左区间对右区间的贡献。这时候左区间是按照x升序排列的,右区间是按照查询先后排列的,这样正好既可以保证求贡献时左区间x的单调与递归右区间时右区间内所有的查询都在。对于右区间的i,将左区间内x所有小于它的加入BIT,维护区间和,如果i是询问则查询BIT中所有y小于它的z之和。

      4) Solve(mid+1,r)

      5) 恢复区间,按照x升序排列

        最后答案加上矩阵的s即可。

      BIT的清理也可通过加时间戳的方式做到。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      5 using namespace std;
      6 
      7 const int N = 2*1e6+10;
      8 const int inf = 1e9+7;
      9 
     10 int n,sz,s,w;
     11 int C[N],flag[N],T,tmp[N];
     12 
     13 struct Node {
     14     int x,y,z,pos,ans;
     15     bool operator<(const Node& rhs) const{
     16         return x<rhs.x;
     17     }
     18     Node(int x=0,int y=0,int z=0) {
     19         this->x=x,this->y=y,this->z=z;
     20         pos=sz; ans=0;
     21     }
     22 }q[N],t[N];
     23 bool cmp(const Node& x,const Node& y)
     24 {
     25     return x.pos<y.pos;
     26 }
     27 
     28 void add(int x,int v)
     29 {
     30     for(;x<=w;x+=x&-x)
     31         if(flag[x]!=T) flag[x]=T,C[x]=v;
     32         else C[x]+=v;
     33 }
     34 int query(int x)
     35 {
     36     int res=0;
     37     for(;x;x-=x&-x)
     38         if(flag[x]==T) res+=C[x];
     39     return res;
     40 }
     41 
     42 void solve(int l,int r)
     43 {
     44     if(l==r) return ;
     45     int mid=(l+r)>>1;
     46     int l1=l,l2=mid+1,i,j;
     47     for(i=l;i<=r;i++) {
     48         if(q[i].pos<=mid) t[l1++]=q[i];
     49         else t[l2++]=q[i];
     50     }
     51     memcpy(q+l,t+l,sizeof(q[0])*(r-l+1));
     52     solve(l,mid);
     53     j=l; T++;
     54     for(i=mid+1;i<=r;i++) {
     55         for(;j<=mid&&q[j].x<=q[i].x;j++)
     56             if(q[j].z!=-inf) add(q[j].y,q[j].z);
     57         if(q[i].z==-inf) q[i].ans+=query(q[i].y);
     58     }
     59     solve(mid+1,r);
     60     l1=l,l2=mid+1; int now=l;
     61     while(l1<=mid||l2<=r) {
     62         if(l2>r||l1<=mid&&q[l1]<q[l2]) t[now++]=q[l1++];
     63         else t[now++]=q[l2++];
     64     }
     65     memcpy(q+l,t+l,sizeof(q[0])*(r-l+1));
     66 }
     67 
     68 void read(int &x)
     69 {
     70     char c=getchar(); x=0;int f=1;
     71     while(!isdigit(c)){ if(c=='-')f=-1; c=getchar(); }
     72     while(isdigit(c)) x=x*10+c-'0' , c=getchar();
     73     x*=f;
     74 }
     75 
     76 int main()
     77 {
     78     read(s),read(w);
     79     int op,x1,y1,x2,y2,z;
     80     while(read(op),op!=3)
     81     {
     82         if(op==1) {
     83             read(x1),read(y1),read(z);
     84             q[++sz]=(Node){x1,y1,z};
     85         } else {
     86             read(x1),read(y1),read(x2),read(y2);
     87             q[++sz]=Node(x1-1,y1-1,-inf);
     88             tmp[sz]=abs(x1-x2+1)*abs(y1-y2+1)*s;
     89             q[++sz]=Node(x1-1,y2,-inf);
     90             q[++sz]=Node(x2,y1-1,-inf);
     91             q[++sz]=Node(x2,y2,-inf);
     92         }
     93     }
     94     sort(q+1,q+sz+1);
     95     solve(1,sz);
     96     sort(q+1,q+sz+1,cmp);
     97     for(int i=1;i<=sz;i++) if(q[i].z==-inf) {
     98         int ans=tmp[i];
     99         ans+=q[i++].ans;
    100         ans-=q[i++].ans;
    101         ans-=q[i++].ans;
    102         ans+=q[i++].ans;
    103         i--;
    104         printf("%d
    ",ans);
    105     }
    106     return 0;
    107 }

      ps:鄙人并非权限汪,如代码不能AC概不负责 :)

  • 相关阅读:
    HDOJ 1846 Brave Game
    并查集模板
    HDU 2102 A计划
    POJ 1426 Find The Multiple
    POJ 3278 Catch That Cow
    POJ 1321 棋盘问题
    CF 999 C.Alphabetic Removals
    CF 999 B. Reversing Encryption
    string的基础用法
    51nod 1267 4个数和为0
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5257561.html
Copyright © 2011-2022 走看看