BZOJ--1176(CDQ分治)

2015-08-09 18:57:08

【传送门】CDQ第一道启蒙题~

题意:最多16万个修改,1万个询问,维护的是一个W*W的矩阵(W<=2000000),每个修改是给一个格子加权值,每个询问是询问一个子矩阵内的权值和。

思路:考虑CDQ分治,首先将子矩阵查问拆分为4个查询,然后容斥搞一下,将所有询问按照 x 轴排序,然后将所有操作按照时间一分为二。

  (1)先处理掉前半边区间的修改对后半边询问造成的影响,由于已经按照 x 轴排序了,所以用一颗树状数组就可以维护点权和。

  (2)然后还原前半边区间的影响。

  (3)将前半边操作放在左边,后半边操作放在右边,然后分治处理两边。

 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include <set>
#include 
#include 
#include <string>
#include 
#include 
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 2000010;

int s,w,m;
int c[2000010];
int ans[200010];

inline int lowbit(int x){ return x & (-x); }

void Update(int x,int d){
    while(x <= w){
        c[x] += d;
        x += lowbit(x);
    }
}

int Getsum(int x){
    int res = 0;
    while(x){
        res += c[x];
        x -= lowbit(x);
    }
    return res;
}

struct node{
    int x,y,id,typ,val,f,pos;
    bool operator < (const node &b) const{
        if(x == b.x && y == b.y) return typ < b.typ;
        if(x == b.x) return y < b.y;
        return x < b.x;
    }
}Q[200010],tmp[200010];

void CDQ(int l,int r){
    if(l == r) return;
    int mid = getmid(l,r);
    CDQ(l,mid); CDQ(mid + 1,r);
    sort(Q + l,Q + r + 1);
    //l -> mid , mid + 1 -> r
    for(int i = l; i <= r; ++i){
        if(Q[i].id <= mid && Q[i].typ == 0)
            Update(Q[i].y,Q[i].val);
        if(Q[i].id > mid && Q[i].typ == 1)
            ans[Q[i].pos] += Q[i].f * Getsum(Q[i].y);
    }
    for(int i = l; i <= r; ++i)
        if(Q[i].id <= mid && Q[i].typ == 0)
            Update(Q[i].y,-Q[i].val);
}

int main(){
    int f,X1,Y1,X2,Y2;
    scanf("%d%d",&s,&w);
    m = 0;
    int ans_cnt = 0;
    while(1){
        scanf("%d",&f);
        if(f == 3) break;
        if(f == 1){
            ++m;
            scanf("%d%d%d",&Q[m].x,&Q[m].y,&Q[m].val);
            Q[m].id = m; Q[m].typ = 0; //修改
        }
        else{
            scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
            ans_cnt++;
            Q[++m].x = X2; Q[m].y = Y2; Q[m].id = m; 
            Q[m].typ = 1; Q[m].f = 1; Q[m].pos = ans_cnt;

            Q[++m].x = X1 - 1; Q[m].y = Y1 - 1; Q[m].id = m;
            Q[m].typ = 1; Q[m].f = 1; Q[m].pos = ans_cnt;

            Q[++m].x = X2; Q[m].y = Y1 - 1; Q[m].id = m; 
            Q[m].typ = 1; Q[m].f = -1; Q[m].pos = ans_cnt;

            Q[++m].x = X1 - 1; Q[m].y = Y2; Q[m].id = m;
            Q[m].typ = 1; Q[m].f = -1; Q[m].pos = ans_cnt;
        }
    }
    CDQ(1,m);
    for(int i = 1; i <= ans_cnt; ++i){
        printf("%d\n",ans[i]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4716049.html

你可能感兴趣的:(BZOJ--1176(CDQ分治))