码迷,mamicode.com
首页 > 其他好文 > 详细

1000F.One Ocurrence(可持久化线段树+思维)

时间:2021-06-02 12:02:18      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:建模   enc   else   能力   wro   getchar   pair   fir   维护   

这题很妙。

多去完成这种级别的题目,建模能力才会真正得到提高。

题解干完springboot活补。

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<‘0‘||c>‘9‘) {if(c==‘-‘) f=-1;c=getchar();}
	while (c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x*f;
}

const int maxn=5e5+100;
//维护每个点后面的最小位置
//什么点在区间内只出现了一次
//用主席树维护
//下标:最近一次出现的位置
//权值:上一次出现的位置的最大值
//一个版本的主席树只保存最近一次出现的位置
//单点更新
int n,a[maxn],q;
const int M=maxn*50;
int c[M],tot,lson[M],rson[M],T[M];
int pp[M];//表示区间最大值下标的位置 
int build (int l,int r) {
	int rt=++tot;
	c[rt]=0;
	pp[rt]=0;
	if (l==r) return rt;
	int mid=(l+r)>>1;
	lson[rt]=build(l,mid);
	rson[rt]=build(mid+1,r);
	return rt;
} 
int up (int root,int l,int r,int p,int v) {
	int newRoot=++tot;
	if (l==r) {
		c[newRoot]=v;
		pp[newRoot]=p;
		return newRoot;
	}
	int mid=(l+r)>>1;
	if (p<=mid) {
		lson[newRoot]=up(lson[root],l,mid,p,v);
		rson[newRoot]=rson[root];
	}
	else {
		rson[newRoot]=up(rson[root],mid+1,r,p,v);
		lson[newRoot]=lson[root];
	}
	c[newRoot]=max(c[lson[newRoot]],c[rson[newRoot]]);
	if (c[newRoot]==c[lson[newRoot]]) pp[newRoot]=pp[lson[newRoot]];
	else pp[newRoot]=pp[rson[newRoot]];
	return newRoot;
}
pair<int,int> query (int root,int l,int r,int L,int R) {
	//查找最近一次出现位置的最大上上次出现位置
	if (l>=L&&r<=R) return make_pair(c[root],pp[root]);
	int mid=(l+r)>>1;
	pair<int,int> ans=make_pair(0,0);
	if (L<=mid) ans=max(ans,query(lson[root],l,mid,L,R));
	if (R>mid) ans=max(ans,query(rson[root],mid+1,r,L,R));
	return ans; 
}  
int nxt[maxn];
int pre[maxn];
int main () {
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	for (int i=n;i>=1;i--) {
		nxt[i]=pre[a[i]];
		pre[a[i]]=i;
	}
	q=read();
	T[n+1]=build(1,n);
	for (int i=n;i>=1;i--) {
		if (nxt[i]) {
			int tt=up(T[i+1],1,n,nxt[i],0);
			T[i]=up(tt,1,n,i,nxt[i]);	
		}
		else {
			T[i]=up(T[i+1],1,n,i,1e9);
		}
	}
	while (q--) {
		int l=read();
		int r=read();
		pair<int,int> tt=query(T[l],1,n,l,r);
		int ans=tt.second;
		if (tt.first<=r) ans=0;
		printf("%d\n",a[ans]);
	}
}

1000F.One Ocurrence(可持久化线段树+思维)

标签:建模   enc   else   能力   wro   getchar   pair   fir   维护   

原文地址:https://www.cnblogs.com/zhanglichen/p/14814794.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!