题目描述
这次是机器人来刷漆啦。先在有n面排列在一起的墙,有一个机器人,每次会对一段墙进行刷漆,把这段墙随机的刷成黑色或者白色。请问机器人刷完之后,这n面墙呈现的颜色会有多少种不同的情况?
输入
第一行一个整数n。接下来n行,表示机器人依次要刷的地方。每行两整数L和R,表示机器人要对 [L,R]这段墙进行刷漆。答案对1000000007取余。
输出
输出最后n面墙呈现的颜色会有多少种不同的情况?
样例输入
3
1 1
2 2
3 3
4
1 3
2 4
1 4
2 3
样例输出
8
4
提示
样例1,每个区间是相互独立的,每个区间都有两种颜色可选,答案2^3
对于30%的数据,n的范围[1,20];
对于60%的数据,n的范围[1,200];
对于80%的数据,n的范围[1,2000];
对于100%的数据,n的范围[1,200000];
首先要明白这是按照顺序刷下来后来刷的会把前面刷的给覆盖掉,所以问题可以转化为请问到最后 1到n这段区间被划分为k个区间答案即为2^k
可以选择每一次刷漆都将这一段区间内的数字重新赋值
80分的数据可以暴力for+mark
然而100分就需要就高效的更新和查找很自然引入了线段树数据结构
如果一个区间[L,R]内有两个或以上不同的数字出现c为-1 查询时遇到-1的时候需要继续将区间劈开两半查询,如果不是-1就可以直接mark一下然后ans*=2
代码如下:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define M 200005
#define Mod 1000000007
using namespace std;
struct node{
int L,R,c;
}tree[4*M];
int ans=1;
bool mark[M];
void Read(int &a){
char ch;a=0;ch=getchar();
while(!(ch>='0'&&ch<='9'))ch=getchar();
while((ch>='0'&&ch<='9')){a=a*10+ch-'0';ch=getchar();}
}
void down(int p){
if(tree[p].c==-1)return;
tree[p*2].c=tree[p*2+1].c=tree[p].c;
}
void up(int p){
if(tree[2*p].c==tree[2*p+1].c)tree[p].c=tree[2*p+1].c;
elsetree[p].c=-1;
}
void build(int L,int R,int p){
tree[p].L=L,tree[p].R=R,tree[p].c=0;
if(L==R)return;
int mid=(L+R)>>1;
build(L,mid,p<<1);
build(mid+1,R,p<<1|1);
}
void update(int L,int R,int p,int x){
if(tree[p].L==L&&tree[p].R==R){
tree[p].c=x;
return;
}
int mid=(tree[p].L+tree[p].R)>>1;
down(p);
if(R<=mid)update(L,R,p<<1,x);
else if(L>mid)update(L,R,p<<1|1,x);
else{
update(L,mid,p<<1,x);
update(mid+1,R,p<<1|1,x);
}
up(p);
}
void query(int L,int R,int p){
if(tree[p].L==L&&tree[p].R==R&&tree[p].c!=-1){
if(!mark[tree[p].c]){
mark[tree[p].c]=1;ans=ans*2%Mod;
}
return;
}
intmid=(tree[p].L+tree[p].R)>>1;
down(p);
if(R<=mid)query(L,R,p<<1);
else if(L>mid)query(L,R,p<<1|1);
else{
query(L,mid,p<<1);
query(mid+1,R,p<<1|1);
}
}
int main(){
intn,a,b;
Read(n);
build(1,n,1);
mark[0]=1;//题目有点坑 一开始的墙是固定的 不能涂黑白颜色
for(inti=1;i<=n;i++){
Read(a);Read(b);
update(a,b,1,i);
}
query(1,n,1);
// for(inti=1;i<=7;i++)printf("%d %d %d\n",tree[i].L,tree[i].R,tree[i].c);
printf("%d",ans);
return0;
}