COGS1752. [BOI2007]摩基亞Mokia(CDQ,樹狀數組)

題目描述

摩爾瓦多的移動電話公司摩基亞(Mokia)設計出了一種新的用戶定位系統。和其餘的定位系統同樣,它可以迅速回答任何形如「用戶C的位置在哪?」的問題,精確到毫米。但其真正高科技之處在於,它可以回答形如「給定區域內有多少名用戶?」的問題。node

在定位系統中,世界被認爲是一個W×W的正方形區域,由1×1的方格組成。每一個方格都有一個座標(x,y),1<=x,y<=W。座標的編號從1開始。對於一個4×4的正方形,就有1<=x<=4,1<=y<=4(如圖):ios

請幫助Mokia公司編寫一個程序來計算在某個矩形區域內有多少名用戶。git

輸入輸出格式

輸入格式:數組

 

有三種命令,意義以下:spa

命令 參數 意義設計

  • 0 W 初始化一個全零矩陣。本命令僅開始時出現一次。
  • 1 x y A 向方格(x,y)中添加A個用戶。A是正整數。
  • 2 X1 Y1 X2 Y2 查詢X1<=x<=X2,Y1<=y<=Y2所規定的矩形中的用戶數量
  • 3 無參數 結束程序。本命令僅結束時出現一次。

 

輸出格式:code

 

對全部命令2,輸出一個一行整數,即當前詢問矩形內的用戶數量。blog

 

輸入輸出樣例

輸入樣例#1:  複製
0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
輸出樣例#1:  複製
3
5

說明

對於全部數據:get

1<=W<=2000000
1<=X1<=X2<=W
1<=Y1<=Y2<=W
1<=x,y<=W
0<A<=10000
命令1不超過160000個。
命令2不超過10000個。it

題解

樹狀數組沒有清空結果調了幾個小時……快瘋了……

座標範圍太大,先考慮離散

咱們把一個操做當作$(a,x,y)$的形式,其中$a$表明時間,$x,y$表明座標(查詢操做能夠經過差分拆成四個操做)

而後就是一個三維偏序問題了,用CDQ+樹狀數組解決

時間這一維是默認有序的

$x$這一維能夠用CDQ自帶的歸併排好序

$y$這一維用樹狀數組就能夠求出答案

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 6 char buf[1<<21],*p1=buf,*p2=buf;
 7 inline int read(){
 8     #define num ch-'0'
 9     char ch;bool flag=0;int res;
10     while(!isdigit(ch=getc()))
11     (ch=='-')&&(flag=true);
12     for(res=num;isdigit(ch=getc());res=res*10+num);
13     (flag)&&(res=-res);
14     #undef num
15     return res;
16 }
17 char sr[1<<21],z[20];int C=-1,Z;
18 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
19 inline void print(int x){
20     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
21     while(z[++Z]=x%10+48,x/=10);
22     while(sr[++C]=z[Z],--Z);sr[++C]='\n';
23 }
24 const int N=200005;
25 struct node{
26     int x,y,d,id;
27     inline void add(int a,int b,int c,int _id=0)
28     {x=a,y=b,d=c,id=_id;}
29     inline bool operator <(const node &b)const{
30         return x!=b.x?x<b.x:
31         y!=b.y?y<b.y:
32         d>b.d;
33     }
34 }a[N],p[N];int n,m,ans[N];
35 int c[N*10];
36 inline void add(int x,int val){
37     for(int i=x;i<=n;i+=i&(-i))
38     c[i]+=val;
39 }
40 inline int query(int x){
41     int res=0;
42     for(int i=x;i;i-=i&(-i))
43     res+=c[i];
44     return res;
45 }
46 inline void clear(int x){
47     for(int i=x;i<=n;i+=i&(-i))
48     if(c[i]) c[i]=0;
49     else return;
50 }
51 void cdq(int l,int r){
52     if(l==r) return;
53     int mid=(l+r)>>1;
54     cdq(l,mid),cdq(mid+1,r);
55     int i=l,j=l,k=mid+1;
56     while(j<=mid&&k<=r){
57         if(p[j]<p[k]){
58             if(p[j].d) add(p[j].y,p[j].d);
59             a[i++]=p[j++];
60         }
61         else{
62             if(!p[k].d) ans[p[k].id]+=query(p[k].y);
63             a[i++]=p[k++];
64         }
65     }
66     while(j<=mid) a[i++]=p[j++];
67     while(k<=r){
68         if(!p[k].d) ans[p[k].id]+=query(p[k].y);
69         a[i++]=p[k++];
70     }
71     for(int i=l;i<=r;++i){
72         clear(a[i].y);p[i]=a[i];
73     }
74 }
75 int main(){
76     //freopen("testdata.in","r",stdin);
77     n=read(),n=read();
78     for(int x,y,xx,yy,opt;(opt=read())!=3;){
79         x=read(),y=read(),xx=read();
80         if(opt&1){
81             p[++m].add(x,y,xx,m+1);
82             ans[m]=-1;
83         }
84         else{
85             yy=read();
86             p[++m].add(xx,yy,0,m+1),p[++m].add(x-1,yy,0,m+1);
87             p[++m].add(xx,y-1,0,m+1),p[++m].add(x-1,y-1,0,m+1);
88         }
89     }
90     cdq(1,m);
91     for(int i=1;i<=m;++i)
92     if(~ans[i]){
93         int k=ans[i]-ans[i+1]-ans[i+2]+ans[i+3];
94         print(k);i+=3;
95     }
96     Ot();
97     return 0;
98 }
相關文章
相關標籤/搜索