2018年6月4号(线段树)
Posted zssmg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018年6月4号(线段树)相关的知识,希望对你有一定的参考价值。
今天想和大家一起了解下今天我刚写的一道题:
题目背景
阿宝上学了,今天老师拿来了一块很长的涂色板。
题目描述
色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, ... L。现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:1. "C A B C" 指在A到 B 号方格中涂上颜色 C。2. "P A B" 指老师的提问:A到 B号方格中有几种颜色。学校的颜料盒中一共有 T 种颜料。为简便起见,我们把他们标记为 1, 2, ... T. 开始时色板上原有的颜色就为1号色。 面对如此复杂的问题,阿宝向你求助,你能帮助他吗?
输入输出格式
输入格式:
第一行有3个整数 L (1 <= L <= 100000), T (1 <= T <= 30) 和 O (1 <= O <= 100000). 在这里O表示事件数, 接下来 O 行, 每行以 "C A B C" 或 "P A B" 得形式表示所要做的事情(这里 A, B, C 为整数, 可能A> B)
输出格式:对于老师的提问,做出相应的回答。每行一个整数。
输入输出样例
输入样例#1: 复制
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
输出样例#1: 复制
2 1
这道题最主要的是处理颜色,首先我们可以想到暴力枚举颜色,经过多年的经验(其实就那么几天);
绝对会超时;
所以我去询问了我们班大佬,打听到一个好方法:用二进制代替有无用这种颜色;
eg:10101表示用了1和3和5编号颜色,没有用其他;
有人会问如何将左子树和右子树合并,所以我们就必须用或(|);
有如下效果:
100
| 001
---------
101
就进行合并了;
所以代码就很好实现:
1 #include<bits/stdc++.h> 2 #define zhi 100001 3 using namespace std; 4 struct node{ 5 int l,r,dis,vis; 6 }tree[zhi*4]; 7 int x,y,t; 8 void buid(int p,int l,int r) 9 { 10 tree[p].l=l; 11 tree[p].r=r; 12 tree[p].dis=1; 13 if(l==r) 14 return ; 15 buid(p*2,l,(l+r)/2); 16 buid(p*2+1,(l+r)/2+1,r); 17 } 18 int zhuang(int s) 19 { 20 int tot=0; 21 while(s!=0) 22 { 23 if(s%2) 24 tot++; 25 s/=2; 26 } 27 return tot; 28 } 29 void pdown(int p) 30 { 31 if(tree[p].vis) 32 { 33 tree[p*2].dis=tree[p].vis; 34 tree[p*2].vis=tree[p].vis; 35 tree[p*2+1].dis=tree[p].vis; 36 tree[p*2+1].vis=tree[p].vis; 37 tree[p].vis=0; 38 } 39 } 40 void xiugai(int p) 41 { 42 if(x<=tree[p].l&&y>=tree[p].r) 43 { 44 tree[p].dis=(1<<t); 45 tree[p].vis=tree[p].dis; 46 return ; 47 } 48 pdown(p); 49 int mid=(tree[p].l+tree[p].r)/2; 50 if(x<=mid) 51 xiugai(p*2); 52 if(y>mid) 53 xiugai(p*2+1); 54 tree[p].dis=tree[p*2].dis|tree[p*2+1].dis; 55 } 56 int ask(int p) 57 { 58 if(x<=tree[p].l&&y>=tree[p].r) 59 return tree[p].dis; 60 pdown(p); 61 int mid=(tree[p].l+tree[p].r)/2,a=0,b=0; 62 if(x<=mid) 63 a=ask(p*2); 64 if(y>mid) 65 b=ask(p*2+1); 66 return a|b; 67 } 68 int main() 69 { 70 char u; 71 int m,n,l,a,b; 72 cin>>n>>m>>l; 73 buid(1,1,n); 74 for(int i=1;i<=l;++i) 75 { 76 cin>>u; 77 cin>>a>>b; 78 x=min(a,b); 79 y=max(a,b); 80 if(u==‘C‘) 81 { 82 cin>>t; 83 t--; 84 xiugai(1); 85 } 86 else 87 printf("%d\n",zhuang(ask(1))); 88 } 89 return 0; 90 }
today is over!
以上是关于2018年6月4号(线段树)的主要内容,如果未能解决你的问题,请参考以下文章