caioj【1101】:统计颜色(模板题) 线段树(lazytag)+离散化
来源:互联网 发布:asp网站sql注入 编辑:程序博客网 时间:2024/06/06 03:47
- 题目大意
- 离散化
- lazytag
- bitset
题目大意:
有L段线段(编号为1~L, (1 <= L <= 1 0000 0000 没错,就是1亿 )) ,一开始全部线段是颜色1。
有两种操作:
1、C A B tt :把第A至第B个线段染成第tt种颜色
2、P A B :询问第A至第B个线段有多少种不一样的颜色。
注意:
1、A有可能比B大。
2、颜色的编号<=50;
离散化
刚get的离散化,虽然没有用一对一的方式记录下来,但是用自带函数还是好接受的。
先贴一下方便看~~~(某位大佬的代码)
scanf("%s%d%d",wen,&li[i],&ri[i]);lisan[tot++]=li[i];lisan[tot++]=ri[i];//将所有端点放在一个数组里,无关乎匹配,因为将来用lower_bound
sort(lisan,lisan+tot); /*一般离散化到这一步就结束了,但是有漏洞,因为我们把所涉及端点排列后直接以+1+1的形式一一映射,所以(例:[3,5]与[8,10])映射之后可能就是挨在一起的一段([1,2]与[3,4])解决方法就是:不连续的两段在离散化以后中间加一个点隔开。*///思想如上述,但是真的插入的时候,是不需要这样的,如下方式还可以避免因为存在重复点而重复插。 int m=unique(lisan,lisan+tot)-lisan; //把冗余的放在后面,返回尾指针,注意,是尾指针,指向排列成unique数列后的下一位 int t=m; for(int i=1;i<=t;i++) if(lisan[i]-lisan[i-1]>1)lisan[m++]=lisan[i-1]+1;//尾部插入间隔点 sort(lisan,lisan+m);//将插入点放到对应位置。
lazytag
纯纯的lazy,唯一值得注意的是lazy不累加,所以每次下放就需要把儿子的颜色集合清空
bitset
就是按照集合的思想,结合计算机位运算,实现压状。太大了bitset< n >地方不够。详细看链接吧。
https://www.cnblogs.com/BaiYiShaoNian/p/4591167.html
完整来代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#include<bitset>const int MAX=500000;using namespace std;struct segtree{ int l,r,lazy; bitset<51>s; segtree(){lazy=0;s.reset();s[1]=1;}}arr[MAX];void build(int p,int l,int r){ arr[p].l=l; arr[p].r=r; if(l==r)return ; int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r);}void down(int p){ if(arr[p].lazy!=0) { int lz=arr[p].lazy;arr[p].lazy=0; int ls=p<<1,rs=p<<1|1; arr[ls].s.reset();arr[ls].s[lz]=1;arr[ls].lazy=lz; arr[rs].s.reset();arr[rs].s[lz]=1;arr[rs].lazy=lz; }}void upp(int p){ arr[p].s=(arr[(p<<1)].s|arr[(p<<1|1)].s);}void insert(int p,int x,int y,int v){ int l=arr[p].l,r=arr[p].r; if(x<=l&&r<=y) { arr[p].s.reset(); arr[p].lazy=v; arr[p].s[v]=1; return ; } down(p); int mid=(l+r)>>1; if(x<=mid)insert(p<<1,x,y,v); if(mid<y)insert(p<<1|1,x,y,v); upp(p);}bitset<51>ans;void query(int p,int x,int y){ int l=arr[p].l,r=arr[p].r; if(x<=l&&r<=y) { ans=(ans|arr[p].s); return ; } down(p); int mid=(l+r)>>1; if(x<=mid)query(p<<1,x,y); if(mid<y)query(p<<1|1,x,y); upp(p);}int li[100500],ri[100500],qes[100500],lisan[201000];int main(){ char wen[8]; int n,q,tot=0; scanf("%d%d",&n,&q); for(int i=1;i<=q;i++) { scanf("%s%d%d",wen,&li[i],&ri[i]); lisan[tot++]=li[i];lisan[tot++]=ri[i]; if(wen[0]=='C'){scanf("%d",&qes[i]);} if(wen[0]=='P'){qes[i]=-1;} } sort(lisan,lisan+tot); int m=unique(lisan,lisan+tot)-lisan; int t=m; for(int i=1;i<=t;i++) if(lisan[i]-lisan[i-1]>1)lisan[m++]=lisan[i-1]+1; sort(lisan,lisan+m); build(1,1,m); for(int i=1;i<=q;i++) { ans.reset();//注意每一次的初始化 int x=lower_bound(lisan,lisan+m,li[i])-lisan+1; int y=lower_bound(lisan,lisan+m,ri[i])-lisan+1; //返回值是指针 //不+1是从0开始的:lisan-lisan=0; if(x>y)swap(x,y);//题有坑,不过养成好习惯。 //printf("(%d,%d)->(%d,%d)\n",li[i],ri[i],x,y); if(qes[i]==(-1)) { query(1,x,y); printf("%d\n",ans.count());//很方便的统计位1的方式。 } else { insert(1,x,y,qes[i]); } } return 0;}
阅读全文
1 0
- caioj【1101】:统计颜色(模板题) 线段树(lazytag)+离散化
- [caioj]1100: [视频]线段树2(统计不同颜色)
- 双lazytag线段树板子
- HDU-1255 覆盖的面积(线段树扫描线模板+离散化+加点修改题)
- [caioj] 问题 E: 单调队列3 (线段树)
- caioj 1099 线段树
- poj 2528 Mayor's posters(线段树+离散化+区间统计)
- NEFU 1215 统计序列和 (线段树模板题)
- hihoCoder - 1079 - 离散化 (线段树 + 离散化)
- hihoCoder 1079 离散化(线段树离散化)
- HIHO #1079 : 离散化(线段树+离散化)
- HDU4902Nice boat (线段树区间更新+lazytag)
- 线段树优化——lazytag
- PKU 2528 (线段树 + 离散化)
- PKU 3277(线段树 + 离散化)
- PKU 3368(线段树 + 离散化)
- hdu_4325 Flowers(离散化+线段树)
- poj2528 (线段树+离散化)
- MySQL简单语法(1)
- C# Linq版七层登录
- Mondriaan's Dream
- 19 迭代器iterator的设计原则(学自Boolean)
- AQSENSE 3D acquisition and processing Tools
- caioj【1101】:统计颜色(模板题) 线段树(lazytag)+离散化
- Java定时任务之Timer的使用
- tddl+diamond(一)
- LeetCode#712 Minimum ASCII Delete Sum for Two Strings题解(C++版)
- HDU-1556-Color the ball
- python excel文件的读写修改保存
- JAVA | 44
- 3DEXPRESS: 3D Machine Vision made easy
- 网站接入微信扫二维码登录 (nodejs)