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";
}
}