Hemose Shopping
可以注意到有一些数字是可以与别人换位置的,有一些是不能的,然后可以与别人换位置的还有这样一个性质, a a a和 b b b不能换,但是他们两个都可以和 c c c换,所以可以通过媒介来将 a a a, b b b来换位置,所以第一个不能换位置的开始的位置就是 m a x ( 1 , n − x + 1 ) max(1,n-x+1) max(1,n−x+1),结束的位置就是 m i n ( x , n ) min(x,n) min(x,n).这个区间的数不能挪动位置,所以先排序,然后看看这个区间的每个数是不是原来的就行了
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 200100
using namespace std;
int T,n,x,a[maxn],b[maxn];
signed main(){
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&x);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
int begin=max(1,n-x+1),end=min(x,n);
sort(a+1,a+1+n);
int flag=false;
for(int i=begin;i<=end;i++){
if(a[i]!=b[i]) {flag=true;break;}
}
if(!flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}
Bakry and Partitioning
先把所有的异或起来记为 s u m sum sum,然后如果所有的异或值为 0 0 0,那么就一定能找到一条边把它拆开,两边的异或值是相等,因为每个点的权值都是大于 1 1 1的.
然后开始 d f s dfs dfs,找到整个值为 s u m sum sum的就 c n t + 1 cnt+1 cnt+1,然后到了最后一定是很多个值为 s u m sum sum的块,然后可能还会有一个值为 0 0 0的块,但是没有关系, 0 0 0的块可以和别人异或,相当于就没了,所最后只要是有大于等于 2 2 2个块是能够分成 s u m sum sum的就行了,如果分出来特别多也没关系,直接 3 3 3个合并就行了
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
vector<int> vt[101000];
int x[101000];
int T,n,k,a,b,all,flag;
int dfs(int now,int fa){
int ans = x[now];
for(int i = 0;i<vt[now].size();i++){
int ed = vt[now][i];
if(ed == fa) continue;
int t = dfs(ed,now);
if(t == all){
flag ++;
}
else{
ans ^= t;
}
}
return ans;
}
signed main(){
scanf("%d",&T);
while(T--){
flag = all=0;
scanf("%d%d",&n,&k);
for(int i = 1;i<=n;i++){
scanf("%d",&x[i]);
all^=x[i];
vt[i].clear();
}
for(int i = 1;i<n;i++){
scanf("%d %d",&a,&b);
vt[a].push_back(b);
vt[b].push_back(a);
}
if(all==0) {printf("YES\n");continue;}
if(k>=3){
dfs(1,0);
if(flag>=2){
printf("YES\n");
continue;
}
}
printf("NO\n");
}
return 0;
}