poj 2777(线段树的节点更新策略)

  1 /*
  2 之前的思想是用回溯的方式进行颜色的更新的!如果用回溯的方法的话,就是将每一个节点的颜色都要更新
  3 通过子节点的颜色情况来判断父节点的颜色情况 !这就是TLE的原因!
  4
  5 后来想一想没有必要 !加入[a, b] 区间有p管辖,那么tree[p]的颜色值就是[a, b]所有点的颜色值!
  6 如果[a,b]的子区间[c,d]没被跟新,那么tree[p]也是[c,d]的值!
  7 否则,在更新[c,d]区间的时候,一定会经过 p 点!然后由上到下更新p<<1 和 p<<1|1 的值!
  8 当找到[c,d]区间所对应的p‘时,并更新p’的值!、
  9
 10 之前的剪枝是点返回, 后面的是线段返回,当然更快!
 11 */
 12 #include<string>
 13 #include<iostream>
 14 #include<algorithm>
 15 #include<cstring>
 16 #include<cstdio>
 17 #define M 100005
 18 using namespace std;
 19
 20
 21 int tree[4*M];
 22
 23 int color[32];
 24 int L, T, O;
 25
 26
 27 void buildT(int ld, int rd, int p){
 28     if(ld<=rd){
 29         tree[p]=1;
 30         if(ld==rd)
 31            return ;
 32          int mid = (ld+rd)/2;
 33          buildT(ld, mid, p<<1);
 34          buildT(mid+1, rd, p<<1|1);
 35     }
 36 }
 37
 38
 39
 40 void updateT(int ld, int rd, int a, int b, int p, int k){
 41     if(tree[p] == k) return ;//如果当前更新的颜色和 之前p所管辖的区间的颜色相同,则返回
 42
 43     if(ld==a && rd==b){//p所管辖的区间的点的颜色全部是k!如果其子区间的颜色被更改,那么
 44         tree[p]=k;     //在更新子区间的时候一定会经过 p点,让后通过p更新 p<<1 和 p<<1|1 子区间的颜色!
 45         return ;
 46     }
 47
 48     if(tree[p]!=-1){//也就是在经过父节点时更新子节点的颜色状态,也就是[a,b]包含在 p点所管辖的区间内
 49        tree[p<<1] = tree[p<<1|1] = tree[p];
 50        tree[p]=-1;
 51     }
 52     if(ld<rd){
 53        int mid = (ld+rd)/2;
 54        if(mid<a)
 55          updateT(mid+1, rd, a, b, p<<1|1, k);
 56        else if(mid>=b)
 57          updateT(ld, mid, a, b, p<<1, k);
 58        else{
 59           updateT(ld, mid, a, mid, p<<1, k);
 60           updateT(mid+1, rd, mid+1, b, p<<1|1, k);
 61        }
 62     }
 63 }
 64
 65 void queryT(int ld, int rd, int a, int b, int p){
 66    if(ld>rd) return ;
 67    if(tree[p]!=-1){
 68          color[tree[p]]=1;
 69    }
 70    else{
 71        int mid = (ld+rd)/2;
 72        if(mid<a)
 73          queryT(mid+1, rd, a, b, p<<1|1);
 74        else if(mid>=b)
 75          queryT(ld, mid, a, b, p<<1);
 76        else{
 77           queryT(ld, mid, a, mid, p<<1);
 78           queryT(mid+1, rd, mid+1, b, p<<1|1);
 79        }
 80    }
 81 }
 82
 83 int main(){
 84
 85    while(scanf("%d%d%d", &L, &T, &O)!=EOF){
 86       buildT(1, L, 1);
 87       while(O--){
 88          char ch[2];
 89          int a, b, c;
 90          scanf("%s", ch);
 91          if(ch[0]==‘C‘){
 92              scanf("%d%d%d", &a, &b, &c);
 93              if(a>b){
 94                a^=b;
 95                b^=a;
 96                a^=b;
 97             }
 98              updateT(1, L, a, b, 1, c);
 99          }
100          else{
101             scanf("%d%d", &a, &b);
102             if(a>b){
103                a^=b;
104                b^=a;
105                a^=b;
106             }
107             memset(color, 0, sizeof(color));
108             queryT(1, L, a, b, 1);
109             int cnt=0;
110             for(int i=1; i<=T; ++i)
111                if(color[i]) ++cnt;
112             printf("%d\n", cnt);
113          }
114       }
115    }
116    return 0;
117 }

poj 2777(线段树的节点更新策略)

时间: 2024-08-03 12:48:35

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 3468 线段树成段更新

http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58132   Accepted: 17704 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two k

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 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 #de

G - Balanced Lineup POJ 3264 (线段树+区间查询无更新)

G - Balanced Lineup Time Limit:5000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3264 Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John de

poj 3669 线段树成段更新+区间合并

添加 lsum[ ] , rsum[ ] , msum[ ] 来记录从左到右的区间,从右到左的区间和最大的区间: #include<stdio.h> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 50005 int rsum[maxn<<2],lsum[maxn<<2],msum[maxn<<2];//msum[]维护区间1…N中的最大连续区间长度 int

POJ 2777 Count Color (线段树成段更新+二进制思维)

题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的颜色有几种. 很明显的线段树成段更新,但是查询却不好弄.经过提醒,发现颜色的种类最多不超过30种,所以我们用二进制的思维解决这个问题,颜色1可以用二进制的1表示,同理,颜色2用二进制的10表示,3用100,....假设有一个区间有颜色2和颜色3,那么区间的值为二进制的110(十进制为6).那我们就把

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace