[BZOJ1176] Mokia (CDQ divide and conquer)

Problem surface

BZOJ permission questions,,,,
dbzoj good.

Description

Maintain a matrix of W*W, the initial value is S. each operation can increase the weight of a grid, or inquire the total weight of a sub matrix. Modify the operation number m < = 160000, inquiry number Q < = 10000, w < = 2000000

Input

Two integers in the first row, S,W; where S is the initial value of the matrix; W is the size of the matrix

Next, for each line, enter one of the following three types (without quotes):

"1 x y a"

"2 x1 y1 x2 y2"

"3"

Input 1: you need to increase the lattice weight of (x, y) (row x, column y) by a

Input 2: you need to find the sum of the weights of all the squares in the matrix whose lower left corner is (x1,y1) and upper right corner is (x2,y2), and output

Input 3: end of input

Output

For each input 2, output one line, i.e. the answer to input 2

Sample Input

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5

HINT

Make sure the answer doesn't exceed int

Title Solution

Obviously, only the changes in the front of time will have an impact on the changes in the back of time.
At the same time, we have three dimensions: time, x-axis and y-axis
So, divide and conquer the time, sort by x,
However, it is very difficult to solve the questions asked after each modification.
We split the inquiry into four questions
What? Which four queries, of course, are two-dimensional prefixes and queries...
Then we can divide and conquer CDQ..

In a word, you can use a tree to cover a tree in seconds at a glance...

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2222222
#define lb(x) (x&(-x))
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int S,n,tot,tim,cntq;
int c[MAX],ans[MAX];
void add(int x,int w){while(x<=n)c[x]+=w,x+=lb(x);}
int getsum(int x){int ret=0;while(x)ret+=c[x],x-=lb(x);return ret;}
struct Opter{int t,x,y,w,ot,id;}q[MAX],tmp[MAX];
bool operator<(Opter a,Opter b)
{
    if(a.x!=b.x)return a.x<b.x;
    if(a.y!=b.y)return a.y<b.y;
    return a.id<b.id;
}
void CDQ(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    for(int i=l;i<=r;++i)
    {
        if(q[i].t<=mid&&q[i].ot==1)add(q[i].y,q[i].w);
        if(q[i].t>mid&&q[i].ot==2)ans[q[i].id]+=q[i].w*getsum(q[i].y);
    }
    for(int i=l;i<=r;++i)
        if(q[i].t<=mid&&q[i].ot==1)add(q[i].y,-q[i].w);
    int t1=l-1,t2=mid;
    for(int i=l;i<=r;++i)
        if(q[i].t<=mid)tmp[++t1]=q[i];
        else tmp[++t2]=q[i];
    for(int i=l;i<=r;++i)q[i]=tmp[i];
    CDQ(l,mid);CDQ(mid+1,r);
}
int main()
{
    S=read();n=read();
    while(233)
    {
        int opt=read();
        if(opt==3)break;
        if(opt==1)
        {
            int x=read(),y=read();
            q[++tot]=(Opter){++tim,x,y,read(),1};
        }
        else
        {
            int x=read(),y=read(),X=read(),Y=read();
            ans[++cntq]=(y-Y+1)*(X-x+1)*S;//++tim;
            q[++tot]=(Opter){++tim,x-1,y-1,+1,2,cntq};
            q[++tot]=(Opter){++tim,X,Y,+1,2,cntq};
            q[++tot]=(Opter){++tim,x-1,Y,-1,2,cntq};
            q[++tot]=(Opter){++tim,X,y-1,-1,2,cntq};
        }
    }
    sort(&q[1],&q[tot+1]);
    CDQ(1,tot);
    for(int i=1;i<=cntq;++i)printf("%d\n",ans[i]);
    return 0;
}

Posted by Weiry on Thu, 02 Apr 2020 21:11:39 -0700