您的位置:首页 > Web前端

【CF484E】Sign on Fence(主席树)

2018-04-02 21:20 176 查看

【CF484E】Sign on Fence(主席树)

题面

懒得贴CF了,你们自己都找得到

洛谷

题解

这不就是[TJOI&HEOI 排序]那题的套路吗。。。

二分一个答案,把大于答案的都变成\(1\),其余变成\(0\)

按照题目要求的区间内连续的\(K\)个

就是检查最长的连续\(1\)的子段长度大于\(K\)

所以维护\(1\)的子段长度(这也是原题吧??)

因为范围比较大,不能每次开线段树计算

我们发现每次将范围增大的时候,在线段树上可以直接做一定的修改

又因为要维护所有的线段树,所以直接主席树维护即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 111111
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Node
{
int ls,rs,l,r,id;
int lm,rm,mm;
}t[MAX*20];
int tot,rt[MAX];
Node operator+(Node a,Node b)
{
Node c;c.ls=a.id;c.rs=b.id;
c.l=a.l;c.r=b.r;c.lm=a.lm;c.rm=b.rm;
if(a.lm==a.r-a.l+1)c.lm+=b.lm;
if(b.lm==b.r-b.l+1)c.rm+=a.rm;
c.mm=max(max(a.mm,b.mm),a.rm+b.lm);
return c;
}
void Modify(int &x,int ff,int l,int r,int p)
{
t[x=++tot]=t[ff];t[x].l=l;t[x].r=r;t[x].id=x;
if(l==r){t[x].lm=t[x].rm=t[x].mm=1;return;}
int mid=(l+r)>>1;
if(p<=mid)Modify(t[x].ls,t[ff].ls,l,mid,p);
else Modify(t[x].rs,t[ff].rs,mid+1,r,p);
t[x]=t[t[x].ls]+t[t[x].rs];t[x].id=x;
}
Node Query(int x,int l,int r,int L,int R)
{
if(l==L&&r==R)return t[x];
int mid=(l+r)>>1;
if(R<=mid)return Query(t[x].ls,l,mid,L,R);
if(L>mid)return Query(t[x].rs,mid+1,r,L,R);
return Query(t[x].ls,l,mid,L,mid)+Query(t[x].rs,mid+1,r,mid+1,R);
}
int n,a[MAX],S[MAX],p[MAX];
bool cmp(int x,int y){return a[x]<a[y];}
int main()
{
n=read();
for(int i=1;i<=n;++i)S[i]=a[i]=read(),p[i]=i;
sort(&S[1],&S[n+1]);
int sum=unique(&S[1],&S[n+1])-S-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[sum+1],a[i])-S;
sort(&p[1],&p[n+1],cmp);
for(int i=n;i;--i)
{
if(a[p[i]]!=a[p[i+1]])Modify(rt[a[p[i]]],rt[a[p[i+1]]],1,n,p[i]);
else Modify(rt[a[p[i]]],rt[a[p[i]]],1,n,p[i]);
}
int Q=read();
while(Q--)
{
int L=read(),R=read(),K=read();
int l=1,r=sum,ans=1;
while(l<=r)
{
int mid=(l+r)>>1;
if(Query(rt[mid],1,n,L,R).mm>=K)ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",S[ans]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: