UVA11402--Ahoy, Pirates!--线段树

来源:互联网 发布:usb转网络接口驱动 编辑:程序博客网 时间:2024/04/29 03:26

In the ancient pirate ages, the PirateLand was divided into two teams of pirates, namely, the Buccaneer and the Barbary pirates. Each pirate’s team was not fixed, sometimes the opponent pirates attacked and he was taken away to the other pirate team. All on a sudden a magician appeared in the Pirate Land, where he was making transition of pirates from their team to other team at his own will. Of course, handy spells were used. The process of changing team was known as mutating.

There were N pirates and all of the pirates have a unique id from 0 to N-1. The great magician could mutate a bunch of pirates with consecutive id’s to another one.

Suppose there were 100 pirates in the pirate land and all of them were Barbary pirates, then the magician could cast a spell to change pirates with id’s from 10 to 33 to Buccaneer pirates. Then the whole pirate land would have 24 Buccaneer and 76 Barbarypirates.

The magician was very fast casting the spell. Once, God started to dislike this. God had favor for the Buccaneer pirates and God asked the magician, “Tell me, how many of the pirates of index from 2 to 30 are Buccaneer pirates?”. Now the magician was puzzled as he was only efficient in casting spells, not in counting J

Being clever enough, the magician captured a clever man from the Earth Land. And unfortunately it’s you! Now you have to answer the God’s questions.

Input

The first line of input will contain number of test cases T.

For each test case:

The first part of the description will be of the pirate land. There could be up to N (1<=N<=1024000) pirates. Each pirate is either assigned to Buccaneer or Barbary Pirate. Buccaneer pirates are described by ‘1’ (ONE) and Barbary pirates are described by ‘0’(ZERO). You have to build a string of the pirates’ description. Each case starts with an integer M (M<=100), where M pair lines follow. In each pair of lines (we call it a set), first has an integerT (T< = 200) and next one has a nonempty string Pirates (consisting of 0 and 1, 0 for Barbary, 1 for Buccaneer, has maximum length of 50). For each pair concatenate the stringPirates, T times. Concatenate all the resulting M sets of strings to build the pirate description. The final concatenated string describes the pirates from index 0 to end (N-1 for N pirates).

Now the next part of the input will contain queries. First line of next part has an integer Q describing number of queries. Each subsequence Q (1<=Q<=1000) lines describe each query. Each query has a string F or E or I or S and two integers, a and b denoting indexes. The meaning of the query string arefollows:

F a b, means, mutate the pirates from index a to b to Buccaneer Pirates.

E a b, means, mutate the pirates from index a to b to Barbary Pirates.

I a b, means, mutate the pirates from index a to b to inverse pirates.

S a b, means, “God’s query” God is asking a question: “Tell me, how many Buccaneer pirates are there from index a tob?”

(a <= b, 0 <= a < n, 0< = b < n, index range are inclusive)

Output

For each test print the case number as the sample output suggests. Then for each of “God’s query”, output the query number, colon (:) and a space and the answer to the query as the sample suggest.

Sample Input Output for Sample Input

2

2

5

10

2

1000

5

F 0 17

I 0 5

S 1 10

E 4 9

S 2 10

3

3

1

4

0

2

0

2

I 0 2

S 0 8

Case 1:

Q1: 5

Q2: 1

Case 2:

Q1: 0

Explanation:

Case1:

The pirate land is as follows (N = 18)

101010101010001000

Before God’s first query it was as follows

000000111111111111


Case 2:

The pirate land is as follows (N=9)

111000000

题意:区间置值,区间翻转。求区间1个数。

思路:区间置值没什么说的。区间翻转。超时了一天、、、先上一发TLE代码、、、

#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define maxn 1100000#define lson id<<1,l,mid#define rson id<<1|1,mid+1,rint key[maxn];char str[58];//维护区间的struct ST{int l,r,set,num,flip;//num就是1的数目}st[maxn<<2];void PushUp(int id){st[id].num = st[id<<1].num + st[id<<1|1].num;}void PushDown(int id){if(st[id].set != -1){st[id<<1].flip = st[id<<1|1].flip = 0;st[id<<1].set = st[id<<1|1].set = st[id].set;if(st[id].set == 1){st[id<<1].num = st[id<<1].r - st[id<<1].l + 1;st[id<<1|1].num = st[id<<1|1].r - st[id<<1|1].l + 1;}else{st[id<<1].num = st[id<<1|1].num = 0;}st[id].set = -1;}if(st[id].flip){if(st[id<<1].set != -1){st[id<<1].set ^= 1;}else st[id<<1].flip ^= 1;st[id<<1].num = st[id<<1].r - st[id<<1].l + 1 - st[id<<1].num;if(st[id<<1|1].set != -1){st[id<<1|1].set ^= 1;}else st[id<<1|1].flip ^= 1;st[id<<1|1].num = st[id<<1|1].r - st[id<<1|1].l + 1 - st[id<<1|1].num;st[id].flip = 0;}}void buildtree(int id,int l,int r){st[id].l = l,st[id].r = r;st[id].set = -1;st[id].flip = 0;if(l == r){st[id].set = st[id].num = key[l];return;}int mid = (l+r) >> 1;buildtree(lson);buildtree(rson);PushUp(id);}void Update(int id,int l,int r,int ope){//ope = 0,置0//ope = 1, 置1//ope = 2, 置2if(st[id].l == l && st[id].r == r){if(ope == 0){st[id].flip = 0;st[id].set = 0;st[id].num = 0;}else if(ope == 1){st[id].flip = 0;st[id].set = 1;st[id].num = r-l+1;}else {if(st[id].set != -1)st[id].set ^= 1;else st[id].flip ^= 1;st[id].num = r-l+1 - st[id].num;}return;}PushDown(id);if(st[id<<1].r >= r)Update(id<<1,l,r,ope);else if(st[id<<1|1].l <= l)Update(id<<1|1,l,r,ope);else {Update(id<<1,l,st[id<<1].r,ope);Update(id<<1|1,st[id<<1|1].l,r,ope);}PushUp(id);}int Query(int id,int l,int r){if(st[id].l == l && st[id].r == r)return st[id].num;PushDown(id);if(st[id<<1].r >= r)return Query(id<<1,l,r);else if(st[id<<1|1].l <= l)return Query(id<<1|1,l,r);else return Query(id<<1,l,st[id<<1].r) + Query(id<<1|1,st[id<<1|1].l,r);}int main(){//freopen("in.txt","r",stdin);int t,cas = 0;scanf("%d",&t);while(t--){cas++;int m;scanf("%d",&m);int pos = 1;while(m--){int n;scanf("%d%s",&n,str);int len = strlen(str);while(n--){for(int i = 0;i < len;i++)key[pos++] = (str[i] == '1');}}buildtree(1,1,pos-1);int q;scanf("%d",&q);printf("Case %d:\n",cas);int qq = 0;while(q--){char ope[2];int u,v;scanf("%s%d%d",ope,&u,&v);u++;v++;if(ope[0] == 'F'){Update(1,u,v,1);}else if(ope[0] == 'E'){Update(1,u,v,0);}else if(ope[0] == 'I'){Update(1,u,v,2);}else if(ope[0] == 'S'){qq++;printf("Q%d: %d\n",qq,Query(1,u,v));}}}return 0;}


正解是要离散化、、

一共有一千个询问,将询问的点和中间的区间都用点去代替。最终只需要最多4001个点。

为毛用strcat函数就会超时。用strcpy函数就不会!!!!

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 8080#define lson id<<1,l,mid#define rson id<<1|1,mid+1,rint X[maxn],uu[maxn],vv[maxn];char str[58],T[1100080];int cnt;int belong[1100000];struct ST{int l,r,num,len,flip,set;}st[maxn<<2];struct Command{char ope[2];int u,v;}com[maxn>>2];int Get_num(int pos){int ans = 0;for(int i = uu[pos]-1;i <= vv[pos] - 1;i++)if(T[i] == '1')ans++;return ans;}int Binary(int x){int l = 1,r = cnt - 1;while(l <= r){int mid = (l+r) >> 1;if(uu[mid] <= x && vv[mid] >= x)return mid;if(uu[mid] > x)r = mid -1;else l = mid + 1;}return 1;}void PushUp(int id){st[id].len = st[id<<1].len + st[id<<1|1].len;st[id].num = st[id<<1].num + st[id<<1|1].num;}void PushDown(int id){if(st[id].set != -1){st[id<<1].flip = st[id<<1|1].flip = 0;st[id<<1].set = st[id<<1|1].set = st[id].set;if(st[id].set){st[id<<1].num = st[id<<1].len;st[id<<1|1].num = st[id<<1|1].len;}else{st[id<<1].num = st[id<<1|1].num = 0;}st[id].set = -1;}if(st[id].flip){if(st[id<<1].set != -1){st[id<<1].set ^= 1;}else st[id<<1].flip ^= 1;st[id<<1].num = st[id<<1].len - st[id<<1].num;if(st[id<<1|1].set != -1){st[id<<1|1].set ^= 1;}else st[id<<1|1].flip ^= 1;st[id<<1|1].num = st[id<<1|1].len - st[id<<1|1].num;st[id].flip = 0;}}void buildtree(int id,int l,int r){st[id].l = l,st[id].r = r;st[id].set = -1,st[id].flip = 0;if(l == r){st[id].num = Get_num(l);st[id].len = vv[l] - uu[l] + 1;return;}int mid = (l+r) >> 1;buildtree(lson);buildtree(rson);PushUp(id);}void Update(int id,int l,int r,int ope){if(st[id].l == l && st[id].r == r){if(ope == 0){st[id].flip = 0;st[id].set = 0;st[id].num = 0;}else if(ope == 1){st[id].flip = 0;st[id].set = 1;st[id].num = st[id].len;}else {if(st[id].set != -1)st[id].set ^= 1;else st[id].flip ^= 1;st[id].num = st[id].len - st[id].num;}return;}PushDown(id);if(st[id<<1].r >= r)Update(id<<1,l,r,ope);else if(st[id<<1|1].l <= l)Update(id<<1|1,l,r,ope);else {Update(id<<1,l,st[id<<1].r,ope);Update(id<<1|1,st[id<<1|1].l,r,ope);}PushUp(id);}int Query(int id,int l,int r){if(st[id].l == l && st[id].r == r)return st[id].num;PushDown(id);if(st[id<<1].r >= r)return Query(id<<1,l,r);else if(st[id<<1|1].l <= l)return Query(id<<1|1,l,r);else return Query(id<<1,l,st[id<<1].r) + Query(id<<1|1,st[id<<1|1].l,r);}int main(){//freopen("in.txt","r",stdin);int t;while(scanf("%d",&t)!=EOF){for(int cas = 1;cas <= t;cas++){int m;scanf("%d",&m);memset(T,'\0',sizeof(T));int count = 0;/*这里这样写会超时。。for(int i = 0;i < m;i++){int n;scanf("%d%s",&n,str);for(int i = 0;i < n;i++)strcat(T,str);}*/for(int i = 0;i < m;i++){int len = strlen(str);for(int i = 0;i < n;i++){strcpy(&T[count],str);count += len;}}int q;scanf("%d",&q);int pos = 0;for(int i = 1;i <= q;i++){scanf("%s%d%d",com[i].ope,&com[i].u,&com[i].v);com[i].u++;com[i].v++;X[pos++] = com[i].u;X[pos++] = com[i].v;}sort(X,X+pos);cnt = 1;for(int i = 0;i < pos;i++){if(i == 0){if(X[i] == 1){uu[cnt] = 1;vv[cnt++] = 1;belong[X[i]] = 1;}else {uu[cnt] = 1;vv[cnt++] = X[i] - 1;uu[cnt] = X[i];vv[cnt++] = X[i];belong[X[i]] = cnt-1;}}else {if(X[i] == X[i-1])continue;if(X[i] - X[i-1] > 1){uu[cnt] = X[i-1] + 1;vv[cnt++] = X[i] - 1;}uu[cnt] = X[i];vv[cnt++] = X[i];belong[X[i]] = cnt-1;}}buildtree(1,1,cnt-1);int qq = 0;printf("Case %d:\n",cas);for(int i = 1;i <= q;i++){int u = belong[com[i].u];int v = belong[com[i].v];if(com[i].ope[0] == 'F'){//int u = Binary(com[i].u);//int v = Binary(com[i].v);Update(1,u,v,1);}else if(com[i].ope[0] == 'I'){//int u = Binary(com[i].u);//int v = Binary(com[i].v);Update(1,u,v,2);}else if(com[i].ope[0] == 'S'){//int u = Binary(com[i].u);//int v = Binary(com[i].v);printf("Q%d: %d\n",++qq,Query(1,u,v));}else {//int u = Binary(com[i].u);//int v = Binary(com[i].v);Update(1,u,v,0);}}}}return 0;}



0 0