敲了n遍....RE愉快的debug了一晚上...发现把#define maxn = 100000 + 10 改成 #define maxn = 100010 就过了....感受一下我呵呵哒的表情....
貌似这个题用了很经典的线段树和位运算。懂了。但不是很懂。确实觉得用的很巧妙。只想说。好坑。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define N = 100010 6 7 struct Tree{ 8 int l,r; 9 int col; // 用一个32位的int型,每一位对应一种颜色,用位运算代替bool col[32] 10 bool cover; // 表示这个区间都被涂上同一种颜色,线段树效率的体现,否则插入就是0(n)了。 11 }tree[N<<2]; 12 13 void PushUp(int rt){ // 最后递归回来再更改父节点的颜色 14 tree[rt].col=tree[L(rt)].col | tree[R(rt)].col; 15 } 16 17 void build(int l, int r, int root) { 18 tree[root].l = l; 19 tree[root].r = r; 20 tree[root].col = 1; 21 tree[root].cover = 1; 22 23 if (l == r) return; 24 int mid = (l+r)/2; 25 build(l, mid, 2*root); 26 build(mid+1, r, 2*root+1); 27 } 28 29 30 void PushDown(int root) { // 把标记向下传递 31 tree[2*root].col = tree[root].col; 32 tree[2*root].cover = 1; 33 tree[2*root+1].col = tree[root].col; 34 tree[2*root+1].cover = 1; 35 tree[root].cover = 0; // 懂了。 36 } 37 void update(int val, int l, int r, int root) { // 更新某个区间的颜色 38 if (l <= tree[root].l && tree[root].r <= r) { 39 tree[root].col = val; // 说明这个区间只包含一种颜色了。而且是val. 所以修改完成、get it!!! 40 tree[root].cover = 1; 41 return ; 42 } 43 44 if (tree[root].col == val) return; // 说明当前的区间内的颜色已经只有这一种了。所以没必要再往下、??剪枝 45 if (tree[root].cover) PushDown(root); // 因为下面可能要修改这个区间的某个子区间的颜色了。 46 // 否则就不断的向下分解区间 47 int mid = (tree[root].l+tree[root].r)/2; 48 if (r <= mid) update(val, l, r, 2*root); 49 else if (l >= mid+1) update(val, l, r, 2*root+1); 50 else { 51 update(val, l, mid, 2*root); 52 update(val, mid+1, r, 2*root+1); 53 } 54 PushUp(root); // 递归修改完孩子节点的颜色后 修改父亲节点的颜色 55 } 56 57 int sum; 58 59 void query(int L,int R,int rt){ 60 if(L<=tree[rt].l && R>=tree[rt].r){ 61 sum |= tree[rt].col; 62 return ; 63 } 64 if(tree[rt].cover){ // 这个区间全部为1种颜色,就没有继续分割区间的必要了 65 sum |= tree[rt].col; // 颜色种类相加的位运算代码 66 return; 67 } 68 int mid=(tree[rt].l+tree[rt].r)>>1; 69 if(R<=mid) 70 query(L,R,L(rt)); 71 else if(L>=mid+1) 72 query(L,R,R(rt)); 73 else{ 74 query(L,mid,L(rt)); 75 query(mid+1,R,R(rt)); 76 } 77 } 78 79 int solve(){ 80 int ans=0; 81 while(sum){ 82 if(sum&1) 83 ans++; 84 sum>>=1; 85 } 86 return ans; 87 } 88 89 void swap(int &a, int &b) { 90 int t = a; 91 a = b; 92 b = t; 93 } 94 95 int main() { 96 int l, n, m; 97 while(~scanf("%d%d%d", &l, &n, &m)) { 98 build(1, l, 1); 99 char op[10]; 100 int a, b, c; 101 102 for (int i=0; i<m; ++i) { 103 scanf("%s", op); 104 if (op[0] == ‘C‘) { 105 scanf("%d%d%d", &a, &b, &c); 106 if (a > b) swap(a, b); 107 update(1<<(c-1), a, b, 1); 108 } 109 else if (op[0] == ‘P‘) { 110 scanf("%d%d", &a, &b); 111 if (a > b) swap(a, b); 112 sum = 0; 113 query(a, b, 1); 114 printf("%d\n",solve()); 115 } 116 } 117 } 118 return 0; 119 }
时间: 2024-11-10 08:04:55