ABC296 博弈+拓扑排序 思维+逆序对

E

博弈 拓扑排序

一个图,先手给一个步数,后手选一个起点,必须在从这个起点出发,走完这个步数后在一个特定终点,问多轮游戏有多少轮是后手必胜的

后手必胜,注意到是在先手指定的步数任意的情况下,那么只有终点在在环上,是后手必胜的,否则先手可以给个很大的步数,让走完之后不可能在这个终点

所以拓扑排序计算非环上点个数

void solve(){
	int n;
	cin>>n;
	
	vector<vector<int>>g(n+1);
	vector<int>a(n+1),in(n+1);
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	
	for(int i=1;i<=n;i++){
		g[a[i]].push_back(a[a[i]]);
		in[a[a[i]]]++;
	}
	
	queue<int>q;
	for(int i=1;i<=n;i++){
		if(!in[i]){
			q.push(i);
		}
	}
	int cnt=0;
	while(q.size()){
		int u=q.front();
		q.pop();
		cnt++;
		for(int v:g[u]){
			if(--in[v]==0){
				q.push(v);
			}
		}
	}
	
	cout<<n-cnt;
}

F

思维 逆序对

给两个数组,每次操作必须选一个数对(i,j,k),ijk互不相同(i,j,k),ijk互不相同(i,j,k),ijk互不相同,然后交换(ai,aj)(bi,bk)(a_i,a_j)(b_i,b_k)(ai,aj)(bi,bk)

问能否把ab变成完全相同的序列?

首先ab包含的元素必须完全相同

然后如果存在相同元素,那么可以让一个数组一直交换两个相同元素,相当于对一个数组没有任何操作,然后不断交换另一个数组中的元素对,最终可以把另一个数组排序,变成和不变的数组完全一样。

如果不存在相同元素,这个比较难想,由于每次选择的i,j,ki,j,ki,j,k互不相同,实际上我们只能通过两次操作来交换元素,也就是abc,bac,bca这样,具体可以看洛谷题解第一条。

又由于没有相同元素,这样每次会让逆序对个数+2/-2,也就是逆序对奇偶性始终不变,那么能把ab相同的条件就是ab的初始逆序对奇偶性相同

计算逆序对树状数组即可

void solve(){
	cin>>n;
	
	vector<int>a(n+1),b(n+1);
	set<int>s;
	multiset<int>s1,s2;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		s.insert(a[i]);
		s1.insert(a[i]);
	}
	for(int i=1;i<=n;i++){
		cin>>b[i];
		s2.insert(b[i]);
	}
	
	if(s1!=s2){
		cout<<"No";
		return;
	}
	if(s.size()<n){
		cout<<"Yes";
		return;
	}
	int cnt1=0,cnt2=0;
	for(int i=1;i<=n;i++){
		cnt1+=ask(n)-ask(a[i]);
		add(a[i],1);
	}
	for(int i=1;i<=n;i++){
		tr[i]=0;
	}
	for(int i=1;i<=n;i++){
		cnt2+=ask(n)-ask(b[i]);
		add(b[i],1);
	}
//	cout<<cnt1<<' '<<cnt2<<'\n';
	if(cnt1%2==cnt2%2){
		cout<<"Yes";
	}
	else{
		cout<<"No";
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值