Solution:
对于区间上的问题,我们都不难想到可以用线段树解决
预处理:
对于一个数 \(a_i\) 记录他左边第一个和它相同的数的位置 \(pre_i\) 然后我们将询问离线后排序
然后我们扫描整个数组:
对于一个询问,我们只在当前枚举的i=r时进行答案统计
对于一个数 \(a_i\) : 它和它先祖的关系如下:
\(ans......pre.......a_i\)
我在线段树上对 \([ans+1,pre]\) 打上 \(1\) 的tag,表示右端点在i,左端点至少要在 \([ans+1,pre]\) 上才能取到颜色 \(a_i\) 的贡献
然后这题就做完了
Code:
P4113 [HEOI2012] 采花
#include<bits/stdc++.h>
const int N=2e6+5;
using namespace std;
int n,cnt,m;
//Segment_Tree
#define ls x<<1
#define rs x<<1|1
struct Segment_Tree{
struct Tree{
int l,r,val,tag;
}t[N<<2];
void pushup(int x)
{
t[x].val=max(t[ls].val,t[rs].val);
}
void pushdown(int x)
{
if(!t[x].tag)return;
////<<"pushdown:"<<t[x].l<<" "<<t[x].r<<"="<<t[x].tag<<"\n";
int tag=t[x].tag;
t[ls].tag+=tag,t[rs].tag+=tag;
t[ls].val+=tag,t[rs].val+=tag;
t[x].tag=0;
return;
}
void build(int x,int l,int r)
{
t[x].l=l,t[x].r=r;
if(l==r)
{
return;
}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
}
void upd(int x,int L,int R,int k)
{
if(R<t[x].l||t[x].r<L)return;
if(R<L)return;
if(L<=t[x].l&&t[x].r<=R)
{
//<<"UPD:"<<t[x].l<<" "<<t[x].r<<"\n";
t[x].val+=k;
t[x].tag+=k;
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(L<=mid)upd(ls,L,R,k);
if(mid<R) upd(rs,L,R,k);
pushup(x);
}
int query(int x,int L,int R)
{
if(L<=t[x].l&&t[x].r<=R)
{
return t[x].val;
}
pushdown(x);
int mid=t[x].l+t[x].r>>1,res=0;
if(L<=mid)res=max(query(ls,L,R),res);
if(mid<R) res=max(query(rs,L,R),res);
return res;
}
}T;
int a[N],pre[N],last[N],ans[N];
struct task{
int l,r,id;
bool operator <(const task t){
return r<t.r;
}
}q[N];
int tot;
int read()
{
int res=0;
char c=getchar();
while(c<'0'||'9'<c)c=getchar();
while('0'<=c&&c<='9')res=(res<<3)+(res<<1)+c-'0',c=getchar();
return res;
}
void work()
{
n=read(),tot=read(),m=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
pre[i]=last[a[i]];
last[a[i]]=i;
}
for(int i=1;i<=m;i++)
{
q[i].l=read();
q[i].r=read();
q[i].id=i;
}
T.build(1,1,n);
sort(q+1,q+1+m);
int now=1;
for(int i=1;i<=n;i++)
{
T.upd(1,pre[pre[i]]+1,pre[i],1);
while(q[now].r==i)
{
ans[q[now].id]=T.query(1,q[now].l,q[now].r);
now++;
}
}
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
}
int main()
{
//freopen("flower.in","r",stdin);
//freopen("flower.out","w",stdout);
work();
}
P1972 [SDOI2009] HH的项链
#include<bits/stdc++.h>
const int N=2e6+5;
using namespace std;
int n,cnt,m;
//Segment_Tree
#define ls x<<1
#define rs x<<1|1
struct Segment_Tree{
struct Tree{
int l,r,val,tag;
}t[N<<2];
void pushup(int x)
{
t[x].val=max(t[ls].val,t[rs].val);
}
void pushdown(int x)
{
if(!t[x].tag)return;
////<<"pushdown:"<<t[x].l<<" "<<t[x].r<<"="<<t[x].tag<<"\n";
int tag=t[x].tag;
t[ls].tag+=tag,t[rs].tag+=tag;
t[ls].val+=tag,t[rs].val+=tag;
t[x].tag=0;
return;
}
void build(int x,int l,int r)
{
t[x].l=l,t[x].r=r;
if(l==r)
{
return;
}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
}
void upd(int x,int L,int R,int k)
{
if(R<t[x].l||t[x].r<L)return;
if(R<L)return;
if(L<=t[x].l&&t[x].r<=R)
{
//<<"UPD:"<<t[x].l<<" "<<t[x].r<<"\n";
t[x].val+=k;
t[x].tag+=k;
return;
}
int mid=t[x].l+t[x].r>>1;
pushdown(x);
if(L<=mid)upd(ls,L,R,k);
if(mid<R) upd(rs,L,R,k);
pushup(x);
}
int query(int x,int L,int R)
{
if(L<=t[x].l&&t[x].r<=R)
{
return t[x].val;
}
pushdown(x);
int mid=t[x].l+t[x].r>>1,res=0;
if(L<=mid)res=max(query(ls,L,R),res);
if(mid<R) res=max(query(rs,L,R),res);
return res;
}
}T;
int a[N],pre[N],last[N],ans[N];
struct task{
int l,r,id;
bool operator <(const task t){
return r<t.r;
}
}q[N];
int tot;
int read()
{
int res=0;
char c=getchar();
while(c<'0'||'9'<c)c=getchar();
while('0'<=c&&c<='9')res=(res<<3)+(res<<1)+c-'0',c=getchar();
return res;
}
void work()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
pre[i]=last[a[i]];
last[a[i]]=i;
}
m=read();
for(int i=1;i<=m;i++)
{
q[i].l=read();
q[i].r=read();
q[i].id=i;
}
T.build(1,1,n);
sort(q+1,q+1+m);
int now=1;
for(int i=1;i<=n;i++)
{
T.upd(1,pre[i]+1,i,1);
while(q[now].r==i)
{
ans[q[now].id]=T.query(1,q[now].l,q[now].r);
now++;
}
}
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
}
int main()
{
//freopen("flower.in","r",stdin);
//freopen("flower.out","w",stdout);
work();
}
标签:pre,P4113,int,HEOI2012,mid,HH,build,ls
From: https://www.cnblogs.com/LG017/p/18590475