【bzoj 1176】Mokia

傳送門~

解題思路

CDQ模板,三維偏序問題。
第一維排序,第二維分治,第三維隨便一個數據結構,這裏用的是樹狀數組。
代碼:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
struct xw {int cl[5],ans;} wt[200005];
struct event{
    int x,y,ans;
    int val,num;
    bool operator <(const event &p) const{
         return num<p.num;
    }
}s[800005],tmp[800005];
int a[2000005];
int si,n,tot,lo;
void add(int num,int x){ for(int i=num;i<=n;i+=i&(-i)) a[i]+=x;}
int ch(int num){
    int j=0;
    for(int i=num;i>0;i-=i&(-i)) j+=a[i];
    return j;
}
void CDQ(int x,int y){
    if(x==y) return ;
    int mid=(x+y)>>1;
    CDQ(x,mid);CDQ(mid+1,y);
    int j=x;
    for(int i=mid+1;i<=y;i++){
        if(!s[i].val) continue;
        while(j<=mid){
           if(s[j].val) j++;    
           else if(s[j].y<=s[i].y) {add(s[j].x,s[j].ans);j++;}
           else break;
        } 
        s[i].ans+=ch(s[i].x);
    }
    for(int i=x;i<j;i++) if(!s[i].val) add(s[i].x,-s[i].ans);
    int tp=x,zi=x,zj=mid+1;
    while(zi<=mid && zj<=y){
        if(s[zi].y<=s[zj].y) {tmp[tp++]=s[zi];zi++;}
        else {tmp[tp++]=s[zj];zj++;}
    }
    while(zi<=mid) {tmp[tp++]=s[zi];zi++;}
    while(zj<=y) {tmp[tp++]=s[zj];zj++;}
    for(int i=x;i<=y;i++) s[i]=tmp[i];
}
int main(){
    int opt,x1,x2,y1,y2;
    scanf("%d%d",&si,&n);
    while(scanf("%d",&opt)==1){
        if(opt==1){
            tot++;s[tot].val=0;
            scanf("%d%d%d",&s[tot].x,&s[tot].y,&s[tot].ans);
        }
        else if(opt==2){
            lo++;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);wt[lo].ans=(x2-x1+1)*(y2-y1+1)*si;
            tot++;s[tot].x=x2;s[tot].y=y2;s[tot].ans=0;s[tot].val=1;s[tot].num=lo;
            tot++;s[tot].x=x1-1;s[tot].y=y1-1;s[tot].ans=0;s[tot].val=2;s[tot].num=lo;
            tot++;s[tot].x=x1-1;s[tot].y=y2;s[tot].ans=0;s[tot].val=3;s[tot].num=lo;
            tot++;s[tot].x=x2;s[tot].y=y1-1;s[tot].ans=0;s[tot].val=4;s[tot].num=lo;
        }
        else break;
    }
    CDQ(1,tot);
    for(int i=1;i<=tot;i++) if(s[i].val) wt[s[i].num].cl[s[i].val]=s[i].ans;
    for(int i=1;i<=lo;i++) printf("%d\n",wt[i].ans+wt[i].cl[1]+wt[i].cl[2]-wt[i].cl[3]-wt[i].cl[4]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章