专栏文章

题解:AT_abc421_f [ABC421F] Erase between X and Y

AT_abc421_f题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minyj92i
此快照首次捕获于
2025/12/02 10:26
3 个月前
此快照最后确认于
2025/12/02 10:26
3 个月前
查看原文
CF 做不进去的蒟蒻先把这题题解写了。
这是把我送进水名的题目。也是我切过的 kenkoooo 分最高的 AtCoder 题。

首先考虑 xx 一定在 yy 前面的做法。
因为加入的数不重,所以一定可以记录每一个数的前驱后继。每一个数都只会被删除一次,所以一定是 O(n)O(n) 的。
回到原问题,需要记录 xxyy 的相对顺序。一个重大结论在于:删数不影响不被删的数的相对顺序。此算法需要离线。
先忽略掉所有的删除操作。把数全部加进去,看数在链表的哪一个位置,得到 xxyy 的相对顺序,然后转化成 xxyy 前的情况。
时间复杂度 O(n)O(n)
CPP
#include<bits/stdc++.h>
#define int long long
#define mp(a,b) make_pair(a,b)
using namespace std;

int q;
int nxt[5*114514],lst[5*114514];

int place[5*114514];	//代表不删除序列的元素顺序! 

int op[5*114514];
int x[5*114514],y[5*114514],z[5*114514];
signed main(){
	cin>>q;
	nxt[0]=q+1,lst[q+1]=0;	//代表节点  
	for(int i=1;i<=q;i++){
		cin>>op[i];
		if(op[i]==1){
			cin>>x[i];
			int lst1=x[i],nxt1=nxt[x[i]];	//代表未来节点的位置 
			nxt[lst1]=i,lst[i]=lst1;
			lst[nxt1]=i,nxt[i]=nxt1;	//代表现在的位置  
		}
		else{
			cin>>y[i]>>z[i]; 
		} 
        int now=0;
        // cout<<'!';
        // while(now!=q+1){
        //     cout<<now<<' ';
        //     now=nxt[now];
        // }
        // cout<<endl;
	}
	int now=0;
	place[now]=1;
	int ptr=1;
	while(now!=q+1){
		now=nxt[now];
		ptr++;
		place[now]=ptr;
		// cout<<now<<' ';
	}
 //    for(int i=0;i<=q;i++){
 //        cout<<'#'<<i<<' '<<place[i]<<endl;
 //    }
	// cout<<endl;
	for(int i=0;i<=q;i++){
		nxt[i]=lst[i]=0;	//更新位置! 离线做法的精髓!  
	} 
	nxt[0]=q+1,lst[q+1]=0;
	for(int i=1;i<=q;i++){
		if(op[i]==1){
			int lst1=x[i],nxt1=nxt[x[i]];	//代表未来节点的位置 
			nxt[lst1]=i,lst[i]=lst1;
			lst[nxt1]=i,nxt[i]=nxt1;	//代表现在的位置  
		}
		else{
			int st=y[i],ed=z[i];
            // cout<<st<<' '<<ed<<endl;
            // cout<<place[st]<<' '<<place
			if(place[st]>place[ed])	swap(st,ed);	//精髓!
			int now=nxt[st];
			int include13=0;
            // cout<<st<<' '<<ed<<endl;
			while(now!=ed){
				int nxt1=nxt[now],lst1=lst[now];
				nxt[lst1]=nxt1,lst[nxt1]=lst1;
				include13+=now;
				nxt[now]=lst[now]=0; 
				now=nxt1;	//代表目前的情况  
			} 
			cout<<include13<<endl;
		} 
		int now=0;
		// cout<<"不朽!"<<' ';
		// while(now!=q+1){
		// 	cout<<now<<' ';
		// 	now=nxt[now];
		// } 
		// cout<<endl;
	} 
	cout<<endl;
	return 0;
} //一定要挽回罗琪钧的遗憾啊,一定会挽回罗琪钧的遗憾的! 

评论

0 条评论,欢迎与作者交流。

正在加载评论...