CF1000F One Occurrence

题面传送门
平生第一次切 c f cf cf F F F题祭
其实这道题主席树也可以做,但是我不会,所以只好用莫队水过
对于这道题,维护一个栈,栈中表示的是当前区间内个数为 1 1 1的元素,再设 f i f_i fi表示 i i i这个元素在栈中的位置,来了一个数时,若是第一次出现,加入栈中,若是第二次出现,把栈中的这个元素与栈顶互换位置之后把这个元素弹出,注意 f f f也要跟着换位置并且弹出后 f i f_i fi要清零。若是取出一个数,那么直接判断是否在栈中,若在栈中,按上面的方法弹出,若是取出后恰好有一个在区间内,那么就加入栈中。答案就取栈顶就好了,若是栈空,那取出来的就是 0 0 0,对答案没有影响。
时限对莫队不友好,记得写奇偶性优化, I / O I/O I/O优化和寄存器
代码实现:

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int a[500039],st[500039],s[500039],ans[500039],h[500039],f[500039];
struct yyy {
	int x,y,num;
}sf[500039];
inline bool cmp(yyy x,yyy y) {
	return (s[x.x]^s[y.x])?(x.x<y.x):((s[x.x]&1)?x.y<y.y:x.y>y.y);
}
inline void read(int &x) {
	char s=getchar();x=0;
	while(s<'0'||s>'9') s=getchar();
	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
inline void print(int x) {
	if(x>9) print(x/10);
	putchar(x%10+48);
}
inline void swap(int &x,int &y) {x^=y;y^=x;x^=y;}
int main() {
	register int i,head=0,l=1,r=0,n,m,k,st[500039];
	scanf("%d",&n);
	k=sqrt(n);
	for(i=1;i<=k;i++) s[i]=1;
	for(i=k+1;i<=n;i++) s[i]=s[i-k]+1;
	for(i=1; i<=n; i++)read(a[i]);
	scanf("%d",&m);
	for(i=1; i<=m; i++) read(sf[i].x),read(sf[i].y),sf[i].num=i;
	sort(sf+1,sf+m+1,cmp);
	for(i=1; i<=m; i++) {
		while(l<sf[i].x) {
			f[a[l]]--;
			if(f[a[l]]==1) st[++head]=a[l],h[a[l]]=head;
			if(!f[a[l]]) h[st[head]]=h[a[l]],swap(st[h[a[l]]],st[head]),head--,h[a[l]]=0;
			l++;
		}
		while(r>sf[i].y){
			f[a[r]]--;
			if(f[a[r]]==1) st[++head]=a[r],h[a[r]]=head;
			if(!f[a[r]]) h[st[head]]=h[a[r]],swap(st[h[a[r]]],st[head]),head--,h[a[r]]=0;
			r--;
		}
		while(l>sf[i].x){
			f[a[--l]]++;
			if(f[a[l]]==1) st[++head]=a[l],h[a[l]]=head;
			if(f[a[l]]==2) h[st[head]]=h[a[l]],swap(st[h[a[l]]],st[head]),head--,h[a[l]]=0;
		}
		while(r<sf[i].y){
			f[a[++r]]++;
			if(f[a[r]]==1) st[++head]=a[r],h[a[r]]=head;
			if(f[a[r]]==2) h[st[head]]=h[a[r]],swap(st[h[a[r]]],st[head]),head--,h[a[r]]=0;
			//printf("%d\n",head);
		}
		if(head) ans[sf[i].num]=st[head];
	}
	for(i=1;i<=m;i++) print(ans[i]),putchar('\n');
}

第一次感受到 c f cf cf毒瘤码农数据结构的威力

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值