求做法的正確性
查看原帖
求做法的正確性
736801
MspAInt楼主2024/10/1 09:12

按 2 操作并查集,对每个集合 f2f2s2f2=if2aibis2_{f2}=\sum_{i\in f2}a_i-b_i,称为小集合。

目的是令所有集合 s2s2 为 0。

按 1 操作并查集,每个集合由数个小集合组成。

考虑对于集合 f1={f21,f22,f23}f1=\{f2_1,f2_2,f2_3\},对 f21,f22f2_1,f2_2 同加,对f22,f23f2_2,f2_3 同减,可以发现这就是 2 操作(s1={s21+1,s22,s231}s1=\{s2_1+1,s2_2,s2_3-1\})。因此配合 1 可以奇偶性不变地改变 s2s2。推广,对于 f13,s1mod2=0|f1|\ge3,s1\bmod2=0 有解。

对于集合 f1=f21,f22f1={f2_1,f2_2},考虑到只能同加同减,必须保证 s21=s22s2_1=s2_2

对于集合 f1=f21f1={f2_1},无法操作,必须 s21=0s2_1=0

此外,若对于操作 1 有 ui=viu_i=v_i,可以随意加减,所在集合必有解。若 ui,viu_i,v_i 所在小集合相同,可以任意改变奇偶性,若所在集合的 s1mod2=0s1\bmod 2=0 有解。

代码:

#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int N=1e5+10;
int T,n,m,f[N],a[N],b[N],slf[N];
LL s2[N],s1[N];
struct mdf{int op,x,y;}q[N];
vector<int>p[N];
bool t[N];

int getfa(int x){return x==f[x]?x:(f[x]=getfa(f[x]));}
void merge(int x,int y){x=getfa(x);y=getfa(y);f[x]=y;}

signed main(){
    // freopen("P6185_11.in","r",stdin);
    //freopen(".out","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]);
        for(int i=1;i<=m;i++)scanf("%d%d%d",&q[i].op,&q[i].x,&q[i].y);
        for(int i=1;i<=n;i++)f[i]=i,slf[i]=s1[i]=s2[i]=0,p[i].clear(),t[i]=0;
        for(int i=1;i<=m;i++)if(q[i].op==2)merge(q[i].x,q[i].y);
        for(int i=1;i<=n;i++)s2[getfa(i)]+=a[i]-b[i],t[i]=(i==getfa(i));
        for(int i=1;i<=m;i++)if(q[i].op==1){
            if(q[i].x==q[i].y)slf[getfa(q[i].x)]=max(slf[getfa(q[i].x)],2);
            else if(getfa(q[i].x)==getfa(q[i].y))slf[getfa(q[i].x)]=max(slf[getfa(q[i].x)],1);
        }
        for(int i=1;i<=m;i++)if(q[i].op==1)merge(q[i].x,q[i].y);
        for(int i=1;i<=n;i++)if(t[i])slf[getfa(i)]=max(slf[getfa(i)],slf[i]);
        for(int i=1;i<=n;i++)if(t[i])s1[getfa(i)]+=s2[i],p[getfa(i)].push_back(s2[i]);
        // for(int i=1;i<=n;i++)printf("%d %d %d,",s1[getfa(i)],p[i].size(),slf[i]);puts("");
        bool ans=1;
        for(int i=1;i<=n;i++)if(i==getfa(i))
            ans=(ans&&
            (p[i].size()>2&&s1[i]%2==0||
            p[i].size()==2&&p[i][0]==p[i][1]||
            p[i].size()==1&&!s1[i]||
            slf[i]==2||
            slf[i]==1&&s1[i]%2==0));
        puts(ans?"YES":"NO");
    }
    return 0;
}
2024/10/1 09:12
加载中...