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 

 

你可能感兴趣的:(ZOJ)