P4113 [HEOI2012] 采花 && P1972 [SDOI2009] HH的项链

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();
}
posted @ 2024-12-06 12:05  liuboom  阅读(20)  评论(0)    收藏  举报