题目链接:https://vjudge.net/problem/POJ-2528#author=0
参考:https://blog.csdn.net/weixin_44077863/article/details/98037868
https://blog.csdn.net/baiyifeifei/article/details/81672170
题意:给区间染色,求最后能看到多少颜色。
思路:区间范围太大,需要离散化。
对于
1
3
1 10
1 3
6 10
正确答案是3,如果按照正常的离散化,或导致3和6连在一起从而少算一种。正确的离散化应该是对于所有边界,如果两个连续的边界的差大于1,就要再添加一个中间值。 但是加上后反而过不了了。
查询操作如果没有l==r的判断是会WA的,按理说应该是TLE或RE才对。
这道题因为颜色种类太多,不能压缩到一个数内,因此删除了pushup操作。sum=-1表示没有颜色或颜色有多种。sum!=-1表示该节点所表示的范围内颜色都是一样的。对于查询的pushdown是可以省略掉的,因为如果当前节点的sum等于-1,就不需要下传标记(因为已经下传过了),如果当前节点sum不等于-1,下传标记反而会多此一举。下传标记后必须将当前节点的sum置-1,否则会因为只更新当前节点表示区间的一部分而使当前节点的颜色不纯从而出错。比如1-4区间,先涂成1,现在想把2-4涂成2,修改到区间1-2时,如果下传标记后sum没有置-1,那么出现1-2是纯色的错误。
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#include <cmath>
#include <set>
#include <fstream>
#include <list>
#include <stack>
#include <map>
using namespace std;
const int maxn=1e5+5;
int p[maxn],vis[maxn];
struct NODE
{
int l,r;
int lazy,sum;
NODE()
{
l=r=lazy=sum=0;
}
} a[maxn*4];
void build(int l,int r,int k)
{
a[k].l=l;
a[k].r=r;
a[k].sum=-1;
if(l==r)
{
return ;
}
int mid=(l+r)/2;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
}
void pushdown(int k)
{
if(a[k].l==a[k].r||a[k].sum==-1)
{
return ;
}
a[k*2].sum=a[k].sum;
a[k*2+1].sum=a[k].sum;
a[k].sum=-1;
}
void add(int l,int r,int L,int R,int k,int val)
{
if(l>R||r<L)
return ;
if(l>=L&&r<=R)
{
a[k].sum=val;
return ;
}
int mid=(l+r)/2;
pushdown(k);
add(l,mid,L,R,k*2,val);
add(mid+1,r,L,R,k*2+1,val);
}
int ans;
void query(int l,int r,int L,int R,int k)
{
if(l>R||r<L)
return ;
// pushdown(k);
if(a[k].sum!=-1)
{
if(!vis[a[k].sum])
{
ans++;
vis[a[k].sum]++;
}
}
else if(l==r)
return ;
else
{
int mid=(l+r)/2;
query(l,mid,L,R,k*2);
query(mid+1,r,L,R,k*2+1);
}
return ;
}
vector <int> v;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(vis,0,sizeof(vis));
ans=0;
v.clear();
int n;
scanf("%d",&n);
for(int i=0; i<2*n; i++)
{
scanf("%d",&p[i]);
v.push_back(p[i]);
}
/* sort(v.begin(),v.end()); //正确的离散化
for(int i=1; i<2*n; i++)
{
if(v[i]-v[i-1]>1)
v.push_back(v[i-1]+1);
}*/
sort(v.begin(),v.end());
unique(v.begin(),v.end());
int maxx=-1;
for(int i=0; i<2*n; i++)
{
p[i]=lower_bound(v.begin(),v.end(),p[i])-v.begin()+1;
maxx=max(maxx,p[i]);
}
build(1,maxx,1);
int cnt=1;
for(int i=0; i<2*n; i+=2)
{
add(1,maxx,p[i],p[i+1],1,cnt++);
}
query(1,maxx,1,maxx,1);
printf("%d\n",ans);
}
return 0;
}