poj 2777线段树应用

敲了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

poj 2777线段树应用的相关文章

poj 2777 线段树的区间更新

Count Color Time Limit: 1000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description Chosen Problem Solving and Program design as an optional course, you are required to solve al

POJ 2777 线段树

链接: http://poj.org/problem?id=2777 题意: 有L个气球,开始颜色为1,每次给l,r之间的气球染色x,然后询问l,r区间有多少种不同的颜色 题解: 因为颜色最多有30种,所以对这30中颜色状态压缩一下,放在线段树里面,这样就容易更新了 最后只要计算一下query返回值得数有多少个1就行了 代码: 31 int L, T, O; 32 int Tree[MAXN << 2]; 33 int Lazy[MAXN << 2]; 34 35 int BitC

poj 2777(线段树+lazy思想) 小小粉刷匠

http://poj.org/problem?id=2777 题目大意 涂颜色,输入长度,颜色总数,涂颜色次数,初始颜色都为1,然后当输入为C的时候将x到y涂为颜色z,输入为Q的时候输出x到y的颜色总数 很明显的区间线段树,然后加lazy思想记录 lazy操作为了避免查找到每一个子节点区间而费时,将查找到的区间作标记,但查找到这个区间或还要继续像下查找的时候 将此区间的数据传给下面两个区间树 因为这题颜色总类只有30种很少,所以偷了个懒,将判断与记录操作合并到一个结构体上了,然后用类似hash的

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

转载::POJ 2991 线段树+计算几何(有c++结构体操作)

POJ 2991 线段树+计算几何 (2011-02-27 21:13:44) 转载▼ 标签: 杂谈 分类: OI 话说这一题真的是很恶心很恶心,不过确实改变了我对线段树的一些看法,算是很经典的题目. 题意:有一个吊车由很多个不同长度的线段组成,一开始是一条长直线起点在(0,0),尾节点在(0,sum[n]),每条线段之间的夹角的初始值是180度.然后有一些操作a. b将第a条线段和a+1之间的夹角变成b度,经过每一次操作都要求出尾节点的坐标. 首先要用到一个计算几何的知识(没学过..请教而来)

poj 2750(线段树的动态规划)

Potted Flower Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4186   Accepted: 1581 Description The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrounded by N pots of f

POJ 2570 线段树

Potted Flower Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class name: Main [Submit] [Status] [Discuss] Description The little cat takes over the management of a new park. There is a large circular statue in

poj 2828 线段树

http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 并且后来的也可以确定----如果从前往后,所有的随时都不是确定的 2.线段树叶子节点直接维护区间(线段)信息,非叶子节点v维护的是以v为树根的整个子树的信息,那么假设父节点rt信息为[l,r]那么左子树维护[l,mid],右子树维护[mid+1,r]的信息.如果如果是前缀和,rt里是1-n的和,左子树1~n/2的和,右子树是n/2+1~n

POJ 3468 线段树+lazy标记

lazy标记 Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to