ZOJ 3018

题意:

op:对平面上任意一个点操作+v;

query:询问矩形[x1,y1,x2,y2]里面所有点v的总和;

矩形大小为20000*20000,比赛的时候看到这道题目第一直觉就是二维树状数组,但范围太大会mle,二维线段树也会mle(之后树套树的二维线段树),比赛结束后各种询问;

方法1:

用map<int,int> mp[N];来减少内存的,只在用到的地方开,没有用到的地方就不开;

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<map>
 6 #include<cstdlib>
 7 #include<cmath>
 8 #include<vector>
 9 #include<cstdlib>
10 using namespace std;
11 const int N=20000+10;
12 map<int,int > mp[N];
13 char s[100];
14 int lowbit(int x){
15     return x&-x;
16 }
17 void update(int x,int y,int v){
18     for (int i=x;i<N;i+=lowbit(i)){
19         for (int j=y;j<N;j+=lowbit(j)){
20             mp[i][j]+=v;
21         }
22     }
23 }
24 int sum(int x,int y){
25     int ret=0;
26     for (int i=x;i;i-=lowbit(i)){
27         for (int j=y;j;j-=lowbit(j)){
28             if (mp[i].find(j)!=mp[i].end()){
29                 ret+=mp[i][j];
30             }
31         }
32     }
33     return ret;
34 }
35 int  getsum(int x1,int y1,int x2,int y2){
36 //    cout<<"---- "<<sum(x2,y2)<<" "<<sum(x1-1,y2)<<" "<<sum(x2,y1-1)<<" "<<sum(x1-1,y1-1)<<endl;
37     return sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1);
38 }
39 int main(){
40     int flag=0;
41     int f=0;
42     while (gets(s)){
43         for (int i=0;i<N;i++) mp[i].clear();
44         while (1){
45             if (s[0]=='I'){
46                 flag=1;
47             }else
48             if (s[0]=='Q'){
49                 flag=2;
50             }else 
51             if (s[0]=='E') break;
52             else if (s[0]>='0' && s[0]<='9'){
53                 int x1,x2,y1,y2,v;
54                 if (flag==1){
55                     sscanf(s,"%d%d%d",&x1,&y1,&v);
56                 //    cout<<"** "<<x1<<" "<<y1<<" "<<v<<endl;
57                     update(x1,y1,v);
58                 }else if (flag==2){
59                     sscanf(s,"%d%d%d%d",&x1,&x2,&y1,&y2);
60                 //    cout<<"/// "<<x1<<" "<<x2<<" "<<y1<<" "<<y2<<endl;
61                     printf("%d\n",getsum(x1,y1,x2,y2));
62                 }
63             }
64             gets(s);
65         }
66     }
67     return 0;
68 }
1 3243951 2013-04-07 20:24:28 Accepted  3018 C++ 2800 15968 Rabbit 

但是时间有点慢;

方法2:

用矩阵树,即二维线段树的另外一种表示方法;

每个点表示一个矩阵,每个结点有4个结点,4个结点分别表示把这个矩阵划分成四个小矩阵,即左上,左下,右上,右下;

View Code
  1 /*
  2 每个结点
  3 struct node{
  4     int l,r,d,u;
  5     int sum;//要维护的结点的信息;
  6     int ch[4];//四个小矩阵的标号;
  7 }T[Maxn];
  8 更新基本同一维线段树,
  9 void update(int l,int r,int d,int u,int rt,int v){
 10     if (l<=T[rt].l && T[rt].r<=r && d<=T[rt].d && T[rt].u<=u){
 11         T[rt].sum+=v;
 12         return;
 13     }
 14 };
 15 int query(int l,int r,int d,int u,int rt){
 16     if (l<=T[rt].l && T[rt].r<=r && d<=T[rt].d && T[rt].u<=u){
 17         return T[rt].sum;
 18     }
 19 };
 20 为了节省空间,只对用到的结点申请内存;
 21 
 22 */
 23 #include<cstdio>
 24 #include<cstdlib>
 25 #include<cstring>
 26 #include<algorithm>
 27 #include<iostream>
 28 #include<map>
 29 #include<vector>
 30 #include<set>
 31 #include<bitset>
 32 #include<string>
 33 #include<cmath>
 34 using namespace std;
 35 const int N=20000*15;
 36 struct node{
 37     int l,r,d,u,sum;
 38     int ch[4];
 39     node(){}
 40     node(int a,int b,int c,int e,int f):l(a),r(b),d(c),u(e),sum(f){}
 41 }T[N];
 42 
 43 int idx;
 44 int Newnode(int l,int r,int d,int u){
 45     idx++;
 46     T[idx]=node(l,r,d,u,0);
 47     memset(T[idx].ch,0,sizeof(T[idx].ch));
 48     return idx;
 49 }
 50 void update(int x,int y,int rt,int v){
 51     if (T[rt].l==T[rt].r && T[rt].u==T[rt].d){
 52         T[rt].sum+=v;
 53         return;
 54     }
 55     int m1=(T[rt].l+T[rt].r)>>1;
 56     int m2=(T[rt].u+T[rt].d)>>1;
 57     if (x<=m1 && y<=m2){//左下
 58         if (T[rt].ch[0]==0){
 59             T[rt].ch[0]=Newnode(T[rt].l,m1,T[rt].d,m2);
 60         }
 61         update(x,y,T[rt].ch[0],v);
 62     }
 63     if (x<=m1 && y>m2){//左上
 64         if (T[rt].ch[1]==0){
 65             T[rt].ch[1]=Newnode(T[rt].l,m1,m2+1,T[rt].u);
 66         }
 67         update(x,y,T[rt].ch[1],v);
 68     }
 69     if (x>m1 && y<=m2){//右下
 70         if (T[rt].ch[2]==0){
 71             T[rt].ch[2]=Newnode(m1+1,T[rt].r,T[rt].d,m2);
 72         }
 73         update(x,y,T[rt].ch[2],v);
 74     }
 75     if (x>m1 && y>m2){//右上
 76         if (T[rt].ch[3]==0){
 77             T[rt].ch[3]=Newnode(m1+1,T[rt].r,m2+1,T[rt].u);
 78         }
 79         update(x,y,T[rt].ch[3],v);
 80     }
 81     T[rt].sum=0;//合并
 82     for (int i=0;i<4;i++){
 83         int c=T[rt].ch[i];
 84         T[rt].sum+=T[c].sum;
 85     }
 86 }
 87 int query(int l,int r,int d,int u,int rt){
 88     if (l<=T[rt].l && T[rt].r<=r && d<=T[rt].d && T[rt].u<=u){
 89         return T[rt].sum;
 90     }
 91     int m1=(T[rt].l+T[rt].r)>>1;
 92     int m2=(T[rt].u+T[rt].d)>>1;
 93     int ret=0;
 94     if (l<=m1 && d<=m2){
 95         if (T[rt].ch[0]!=0){
 96             ret+=query(l,r,d,u,T[rt].ch[0]);
 97         }
 98     }
 99     if (l<=m1 && m2<u){
100         if (T[rt].ch[1]!=0){
101             ret+=query(l,r,d,u,T[rt].ch[1]);
102         }
103     }
104     if (m1< r && d<=m2){
105         if (T[rt].ch[2]!=0){
106             ret+=query(l,r,d,u,T[rt].ch[2]);
107         }
108     }
109     if (m1< r && m2< u){
110         if (T[rt].ch[3]!=0){
111             ret+=query(l,r,d,u,T[rt].ch[3]);
112         }
113     }
114     return ret;
115 }
116 char s[100];
117 int main(){
118     int flag=0;
119     while (gets(s)){
120         idx=0;
121         Newnode(1,20000,1,20000);
122         while (1){
123             if (s[0]=='I'){
124                 flag=1;
125             }else
126             if (s[0]=='Q'){
127                 flag=2;
128             }else
129             if (s[0]=='E') break;
130             else if (s[0]>='0' && s[0]<='9'){
131                 int x1,x2,y1,y2,v;
132                 if (flag==1){
133                     sscanf(s,"%d%d%d",&x1,&y1,&v);
134                 //    cout<<"** "<<x1<<" "<<y1<<" "<<v<<endl;
135                     update(x1,y1,1,v);
136                 //    cout<<"++++ "<<T[1].sum<<endl;
137                 }else if (flag==2){
138                     sscanf(s,"%d%d%d%d",&x1,&x2,&y1,&y2);
139                     //cout<<"/// "<<x1<<" "<<x2<<" "<<y1<<" "<<y2<<endl;
140                     printf("%d\n",query(x1,x2,y1,y2,1));
141                 }
142             }
143             gets(s);
144         }
145     }
146     return 0;
147 }
1 3244125 2013-04-07 22:45:19 Accepted  3018 C++ 670 10732 Rabbit 
原文地址:https://www.cnblogs.com/Rlemon/p/3006419.html