题目链接: lines
题意
求相交区间的最大的相交次数。
思路
先离散化处理,再用线段树求每段区间的相交次数,这个线段树的每个节点代表这段区间的总相交次数,最后再比较每个小区间的相交次数,找最大值。
#include <bits/stdc++.h>
using namespace std;
const int maxn=50001;
int addmark[maxn<<3],seqtree[maxn<<3],miner;
void pushdown(int node,int begin,int end)
{
int mid=(begin+end)/2;
if(!addmark[node])
return;
addmark[node<<1]+=addmark[node];
addmark[node<<1|1]+=addmark[node];
seqtree[node<<1]+=addmark[node]*(mid-begin+1);
seqtree[node<<1|1]+=addmark[node]*(end-mid);
addmark[node]=0;
}
void update(int node,int begin,int end,int l,int r,int k)
{
if(l>end || r<begin)
return;
if(l<=begin && r>=end)
{
seqtree[node]+=k*(end-begin+1);
addmark[node]+=k;
return;
}
pushdown(node,begin,end);
int mid=(begin+end)/2;
update(node<<1,begin,mid,l,r,k);
update(node<<1|1,mid+1,end,l,r,k);
seqtree[node]=seqtree[node<<1]+seqtree[node<<1|1];
}
void query(int node,int begin,int end,int l,int r)
{
if(begin==end)
{
if(seqtree[node]>miner)
{
miner=seqtree[node];
}
return;
}
pushdown(node,begin,end);
int mid=(begin+end)/2;
query(node<<1,begin,mid,l,r);
query(node<<1|1,mid+1,end,l,r);
}
int main()
{
int p,t,i,n,a[maxn],b[maxn],lisan[4*maxn];
cin.tie(0);
ios::sync_with_stdio(0);
cin>>p;
while(p--)
{
miner=-1;
cin>>n;
int tot=0;
for(i=0;i<n;i++)
{
cin>>a[i]>>b[i];
lisan[tot++]=a[i];
lisan[tot++]=b[i];
}
sort(lisan,lisan+tot);
int m=unique(lisan,lisan+tot)-lisan;
t=m;
for(i=0;i<t-1;i++)
{
if(lisan[i+1]-lisan[i]>1)
lisan[m++]=lisan[i]+1;
}
sort(lisan,lisan+m);
memset(seqtree,0,sizeof(seqtree));
memset(addmark,0,sizeof(addmark));
for(i=0;i<n;i++)
{
int l=lower_bound(lisan,lisan+m,a[i])-lisan;
int r=lower_bound(lisan,lisan+m,b[i])-lisan;
update(1,0,m-1,l,r,1);
}
query(1,0,m-1,0,m-1);
printf("%d\n",miner);
}
}
题目链接: Mayor’s posters
题意
贴n张海报,每个海报有不同的颜色,占据一定区间,后来的海报可能会遮挡原来的海报,问最后墙上有几种颜色
思路
我强力怀疑题中的数据范围,因为数组的原因WA,RE到怀疑人生,这个题的线段树还有些不同于一般的线段树,一般线段树的节点代表这段区间的最大值或最小值或者是和,如果需要区间更新,需要用到延迟数组,这道题只用一个seqtree[]数组即可,不需要延迟数组,因为每个节点代表这段区间的此时的值,同时也可以代替延迟数组往下更新。query函数也不太一样,我们遍历整棵树,看看共有多少个不同的数字就代表有几种颜色。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=20100;
int ans,vis[4*maxn],seqtree[maxn<<4],addmark[maxn<<4];
void pushdown(int node)
{
if(seqtree[node]!=-1)
{
seqtree[node<<1]=seqtree[node<<1|1]=seqtree[node];
seqtree[node]=-1;
}
}
void update(int node,int begin,int end,int l,int r,int k)
{
if(l>end || r<begin)
return;
if(l<=begin && r>=end)
{
seqtree[node]=k;
return;
}
pushdown(node);
int mid=(begin+end)/2;
update(node<<1,begin,mid,l,r,k);
update(node<<1|1,mid+1,end,l,r,k);
}
void query(int node,int begin,int end,int l,int r)
{
if(seqtree[node]!=-1)
{
if(!vis[seqtree[node]])
{
vis[seqtree[node]]=1;
ans++;
}
}
if(begin==end)
return;
pushdown(node);
int mid=(begin+end)/2;
query(node<<1,begin,mid,l,r);
query(node<<1|1,mid+1,end,l,r);
}
int main()
{
int p,tot,n,a[maxn*4],b[maxn*4],lisan[8*maxn],t,i;
cin>>p;
while(p--)
{
t=0;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i]>>b[i];
lisan[tot++]=a[i];
lisan[tot++]=b[i];
}
sort(lisan,lisan+tot);
int m=unique(lisan,lisan+tot)-lisan;
t=m;
for(i=0;i<t-1;i++)
{
if(lisan[i+1]-lisan[i]>1)
lisan[m++]=lisan[i]+1;
}
sort(lisan,lisan+m);
memset(seqtree,-1,sizeof(seqtree));
memset(vis,0,sizeof(vis));
for(i=0;i<n;i++)
{
int l=lower_bound(lisan,lisan+m,a[i])-lisan;
int r=lower_bound(lisan,lisan+m,b[i])-lisan;
update(1,0,m-1,l,r,i);
}
ans=0;
query(1,0,m-1,0,m-1);
cout<<ans<<endl;
}
}