2019 ICPC Asia Xuzhou Regional(A,C,E,F,H,L,M)

A. Cat
对于一个x,如果x为偶数,有x XOR x+1 XOR x+2 XOR x+3==0,因此对于这个题只有考虑左右边界几个点的异或情况。

#include
using namespace std;
typedef long long ll;
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        ll l,r,s;scanf("%lld%lld%lld",&l,&r,&s);
        ll ans=0;
        if(r-l+1<=10)
        {
            for(ll i=l;i<=r;i++)
            {
                ll res=0;
                for(ll j=i;j<=r;j++)
                {
                    res^=j;
                    if(res<=s) ans=max(ans,j-i+1);
                }
            }
        }
        else
        {
            ll t=0;
            bool flag=false;
            if(l&1) t=l++,flag=true;
            ll sum=0;
            ans=(r-l+1)/4*4;
            if(flag&&t<=s) ans++;
            for(ll i=l+(r-l+1)/4*4;i<=r;i++)
            {
                sum^=i;
                if(sum<=s) ans=max(ans,i-l+1);
                if(flag&&(sum^t)<=s)
                    ans=max(ans,i-l+2);
            }
        }
        if(ans==0) ans=-1;
        printf("%lld\n",ans);
    }
}

C. < 3 numbers
如果区间比较大,显然素数密度一定小于三分之一,直接输出Yes,否则使用区间筛。

#include
using namespace std;
typedef long long ll;
const int N=1e6+10;
bool vis[N];
int tot,p[N];
int solve(int l,int r)
{
    memset(vis,false,sizeof(vis));
    int t=sqrt(r);
    for(int i=1;i<=tot&&p[i]<=t;i++)
        for(int j=l/p[i]*p[i];j<=r;j+=p[i])
            if(j>=l&&j!=p[i]) vis[j-l]=true;
    int ans=0;
    for(int i=l;i<=r;i++)
        if(!vis[i-l]) ans++;
    return ans;
}
int main()
{
    for(int i=2;i<N;i++)
        if(!vis[i])
    {
        p[++tot]=i;
        for(int j=i+i;j<N;j+=i)
            vis[j]=true;
    }
    int t;scanf("%d",&t);
    while(t--)
    {
        int l,r;scanf("%d%d",&l,&r);
        if(r-l+1>=10000) printf("Yes\n");
        else
        {
            int sum=solve(l,r);
            if(3*sum<r-l+1) printf("Yes\n");
            else printf("No\n");
        }
    }
}

E. Multiply
这个题显然就时求z包含x的因子的个数和y!中包含因子的个数。

求法和http://www.51nod.com/Challenge/Problem.html#problemId=1003这个题一样。

但是要对x进行质因数分解,那么就用到Miller Rabin+Pollard-Rho(洛谷P4718)板子就行了。

#include
using namespace std;
const int N=1e5+5;
typedef long long ll;
ll ans;
ll mul(ll a,ll b,ll mod)
{
    return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
}
ll qpow(ll a,ll n,ll mod)
{
    ll ans=1;
    while(n)
    {
        if(n&1) ans=mul(ans,a,mod);
        a=mul(a,a,mod);
        n>>=1;
    }
    return ans;
}
bool mr(ll x,ll b)
{
    ll k=x-1;
    while(k)
    {
        ll cur=qpow(b,k,x);
        if(cur!=1&&cur!=x-1) return false;
        if((k&1)==1||cur==x-1) return true;
        k>>=1;
    }
    return true;
}
bool prim(ll x)//素数测试,如果数据范围大于1e16可以多随机几个素数a进行mr(x,a)测试
{
    if(x==46856248255981ll||x<2) return false;
    if(x==2||x==3||x==7||x==61||x==24251) return true;
    return mr(x,2)&&mr(x,61);
}
ll pr(ll x)
{
    ll s=0,t=0,c=rand()%(x-1)+1;
    int st=0,go=1;
    ll val=1;
    for(go=1;;go<<=1,s=t,val=1)
    {
        for(st=1;st<=go;st++)
        {
            t=(mul(t,t,x)+c)%x;
            val=mul(val,abs(t-s),x);
            if((st%127)==0)
            {
                ll d=__gcd(val,x);
                if(d>1) return d;
            }
        }
        ll d=__gcd(val,x);
        if(d>1) return d;
    }
}
void fac(ll x)
{
    if(x<=ans||x<2) return;
    if(prim(x)) {ans=max(ans,x);return;}
    ll p=x;
    while(p>=x)
        p=pr(x);
    while(x%p==0) x/=p;
    fac(x);fac(p);
}
int n;
ll x,y,a[N];
vector<pair<ll,int> >v;
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d%lld%lld",&n,&x,&y);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        v.clear();
        while(true)
        {
            ans=0;
            fac(x);
            int res=0;
            while(x%ans==0)
            {
                res++;x/=ans;
            }
            v.push_back({ans,res});
            if(x==1) break;
        }
        ans=1e18;
        for(int i=0;i<v.size();i++)
        {
            ll fi=v[i].first,se=v[i].second,sum=0;
            for(int j=1;j<=n;j++)
            {
                ll t=a[j];
                while(t)
                {
                    t/=fi;
                    sum-=t;
                }
            }
            ll t=y;
            while(t)
            {
                t/=fi;
                sum+=t;
            }
            ans=min(ans,sum/se);
        }
        printf("%lld\n",ans);
    }
}

F. The Answer to the Ultimate Question of Life, The Universe, and Everything
把两位的和存入表中,然后枚举第三维,打个表

#include
#define inf 6666
using namespace std;
typedef long long ll;
const int N=205;
struct node
{
    int x,y,z;
    node(){x=y=z=inf;}
};
unordered_map<ll,pair<int,int> >mp;
node ans[N];
int main()
{
    /*
    for(int i=-5000;i<=5000;i++)
        for(int j=i;j<=5000;j++)
    {
        ll s=(ll)i*i*i+(ll)j*j*j;
        mp[s].first=i;mp[s].second=j;
    }
    for(int i=0;i<=200;i++)
    {
        for(int j=-5000;j<=5000;j++)
        {
            ll s=i-(ll)j*j*j;
            if(mp[s].first!=0||mp[s].second!=0)
            {
                ans[i].x=mp[s].first;ans[i].y=mp[s].second;
                ans[i].z=j;
                break;
            }
            else if(s==0)
            {
                ans[i].x=0;ans[i].y=0;ans[i].z=j;break;
            }
        }
        if(ans[i].x!=inf)
        {
            printf("ans[%d].x=%d;ans[%d].y=%d;ans[%d].z=%d;\n",i,ans[i].x,i,ans[i].y,i,ans[i].z);
        }
    }
    */
    ans[0].x=0;ans[0].y=5000;ans[0].z=-5000;
    ans[1].x=1;ans[1].y=5000;ans[1].z=-5000;
    ans[2].x=-486;ans[2].y=4375;ans[2].z=-4373;
    ans[3].x=4;ans[3].y=4;ans[3].z=-5;
    ans[6].x=-205;ans[6].y=644;ans[6].z=-637;
    ans[7].x=44;ans[7].y=168;ans[7].z=-169;
    ans[8].x=2;ans[8].y=5000;ans[8].z=-5000;
    ans[9].x=-52;ans[9].y=217;ans[9].z=-216;
    ans[10].x=-353;ans[10].y=683;ans[10].z=-650;
    ans[11].x=-641;ans[11].y=843;ans[11].z=-695;
    ans[12].x=7;ans[12].y=10;ans[12].z=-11;
    ans[15].x=-262;ans[15].y=332;ans[15].z=-265;
    ans[16].x=-588;ans[16].y=4118;ans[16].z=-4114;
    ans[17].x=2195;ans[17].y=2977;ans[17].z=-3331;
    ans[18].x=-1276;ans[18].y=1671;ans[18].z=-1373;
    ans[19].x=47;ans[19].y=91;ans[19].z=-95;
    ans[20].x=-741;ans[20].y=2833;ans[20].z=-2816;
    ans[21].x=-287;ans[21].y=445;ans[21].z=-401;
    ans[24].x=8;ans[24].y=8;ans[24].z=-10;
    ans[25].x=1839;ans[25].y=2357;ans[25].z=-2683;
    ans[26].x=237;ans[26].y=2106;ans[26].z=-2107;
    ans[27].x=3;ans[27].y=5000;ans[27].z=-5000;
    ans[28].x=-249;ans[28].y=2269;ans[28].z=-2268;
    ans[29].x=-69;ans[29].y=235;ans[29].z=-233;
    ans[34].x=-244;ans[34].y=1557;ans[34].z=-1555;
    ans[35].x=-509;ans[35].y=1154;ans[35].z=-1120;
    ans[36].x=2358;ans[36].y=2731;ans[36].z=-3223;
    ans[37].x=-84;ans[37].y=445;ans[37].z=-444;
    ans[38].x=16;ans[38].y=25;ans[38].z=-27;
    ans[43].x=-307;ans[43].y=837;ans[43].z=-823;
    ans[44].x=-5;ans[44].y=8;ans[44].z=-7;
    ans[45].x=1709;ans[45].y=2025;ans[45].z=-2369;
    ans[46].x=-473;ans[46].y=815;ans[46].z=-758;
    ans[47].x=49;ans[47].y=139;ans[47].z=-141;
    ans[48].x=-1247;ans[48].y=3991;ans[48].z=-3950;
    ans[51].x=602;ans[51].y=659;ans[51].z=-796;
    ans[53].x=1518;ans[53].y=2141;ans[53].z=-2370;
    ans[54].x=-648;ans[54].y=3891;ans[54].z=-3885;
    ans[55].x=1837;ans[55].y=3131;ans[55].z=-3329;
    ans[56].x=505;ans[56].y=559;ans[56].z=-672;
    ans[57].x=361;ans[57].y=982;ans[57].z=-998;
    ans[60].x=-163;ans[60].y=1202;ans[60].z=-1201;
    ans[61].x=668;ans[61].y=845;ans[61].z=-966;
    ans[62].x=-1561;ans[62].y=2903;ans[62].z=-2744;
    ans[63].x=102;ans[63].y=146;ans[63].z=-161;
    ans[64].x=4;ans[64].y=5000;ans[64].z=-5000;
    ans[65].x=403;ans[65].y=903;ans[65].z=-929;
    ans[66].x=1;ans[66].y=4;ans[66].z=1;
    ans[69].x=134;ans[69].y=398;ans[69].z=-403;
    ans[70].x=824;ans[70].y=2325;ans[70].z=-2359;
    ans[71].x=401;ans[71].y=443;ans[71].z=-533;
    ans[72].x=-104;ans[72].y=434;ans[72].z=-432;
    ans[73].x=-146;ans[73].y=344;ans[73].z=-335;
    ans[78].x=-829;ans[78].y=2123;ans[78].z=-2080;
    ans[79].x=-196;ans[79].y=711;ans[79].z=-706;
    ans[80].x=-706;ans[80].y=1366;ans[80].z=-1300;
    ans[81].x=-1719;ans[81].y=2638;ans[81].z=-2368;
    ans[82].x=847;ans[82].y=1188;ans[82].z=-1317;
    ans[83].x=1315;ans[83].y=3651;ans[83].z=-3707;
    ans[87].x=-1972;ans[87].y=4271;ans[87].z=-4126;
    ans[88].x=-1282;ans[88].y=1686;ans[88].z=-1390;
    ans[89].x=1953;ans[89].y=2036;ans[89].z=-2514;
    ans[90].x=365;ans[90].y=1798;ans[90].z=-1803;
    ans[91].x=-2912;ans[91].y=3992;ans[91].z=-3389;
    ans[92].x=861;ans[92].y=4039;ans[92].z=-4052;
    ans[93].x=-98;ans[93].y=253;ans[93].z=-248;
    ans[96].x=14;ans[96].y=20;ans[96].z=-22;
    ans[97].x=-991;ans[97].y=3200;ans[97].z=-3168;
    ans[98].x=-1638;ans[98].y=2391;ans[98].z=-2101;
    ans[99].x=-622;ans[99].y=984;ans[99].z=-893;
    ans[100].x=-903;ans[100].y=1870;ans[100].z=-1797;
    ans[101].x=319;ans[101].y=2325;ans[101].z=-2327;
    ans[102].x=118;ans[102].y=229;ans[102].z=-239;
    ans[105].x=-4;ans[105].y=8;ans[105].z=-7;
    ans[106].x=-1165;ans[106].y=2760;ans[106].z=-2689;
    ans[107].x=947;ans[107].y=1117;ans[107].z=-1309;
    ans[108].x=-948;ans[108].y=1345;ans[108].z=-1165;
    ans[109].x=853;ans[109].y=2924;ans[109].z=-2948;
    ans[111].x=-2312;ans[111].y=4966;ans[111].z=-4793;
    ans[115].x=8;ans[115].y=11;ans[115].z=-12;
    ans[116].x=-757;ans[116].y=1945;ans[116].z=-1906;
    ans[117].x=-555;ans[117].y=962;ans[117].z=-896;
    ans[118].x=383;ans[118].y=4327;ans[118].z=-4328;
    ans[119].x=-1673;ans[119].y=3789;ans[119].z=-3677;
    ans[120].x=1219;ans[120].y=2725;ans[120].z=-2804;
    ans[123].x=-16;ans[123].y=38;ans[123].z=-37;
    ans[124].x=0;ans[124].y=5;ans[124].z=-1;
    ans[125].x=5;ans[125].y=5000;ans[125].z=-5000;
    ans[126].x=-419;ans[126].y=2217;ans[126].z=-2212;
    ans[127].x=-3881;ans[127].y=4988;ans[127].z=-4034;
    ans[128].x=-726;ans[128].y=3997;ans[128].z=-3989;
    ans[129].x=-1238;ans[129].y=1801;ans[129].z=-1580;
    ans[132].x=2;ans[132].y=5;ans[132].z=-1;
    ans[133].x=167;ans[133].y=389;ans[133].z=-399;
    ans[134].x=-1766;ans[134].y=3203;ans[134].z=-3013;
    ans[135].x=-629;ans[135].y=1395;ans[135].z=-1351;
    ans[136].x=816;ans[136].y=946;ans[136].z=-1116;
    ans[137].x=-428;ans[137].y=801;ans[137].z=-758;
    ans[138].x=-77;ans[138].y=103;ans[138].z=-86;
    ans[141].x=104;ans[141].y=116;ans[141].z=-139;
    ans[142].x=-3;ans[142].y=8;ans[142].z=-7;
    ans[144].x=-2552;ans[144].y=3342;ans[144].z=-2746;
    ans[145].x=-7;ans[145].y=10;ans[145].z=-8;
    ans[146].x=-263;ans[146].y=376;ans[146].z=-327;
    ans[147].x=1528;ans[147].y=2131;ans[147].z=-2366;
    ans[150].x=260;ans[150].y=317;ans[150].z=-367;
    ans[151].x=215;ans[151].y=447;ans[151].z=-463;
    ans[152].x=486;ans[152].y=741;ans[152].z=-805;
    ans[153].x=-695;ans[153].y=3744;ans[153].z=-3736;
    ans[154].x=-516;ans[154].y=2145;ans[154].z=-2135;
    ans[155].x=-1049;ans[155].y=3721;ans[155].z=-3693;
    ans[159].x=383;ans[159].y=1526;ans[159].z=-1534;
    ans[160].x=-1654;ans[160].y=3972;ans[160].z=-3874;
    ans[161].x=-2476;ans[161].y=4980;ans[161].z=-4767;
    ans[162].x=-1417;ans[162].y=4180;ans[162].z=-4125;
    ans[163].x=-2943;ans[163].y=4033;ans[163].z=-3423;
    ans[164].x=-59;ans[164].y=79;ans[164].z=-66;
    ans[168].x=-574;ans[168].y=890;ans[168].z=-802;
    ans[169].x=-1012;ans[169].y=1521;ans[169].z=-1354;
    ans[170].x=-2149;ans[170].y=4047;ans[170].z=-3834;
    ans[171].x=891;ans[171].y=1178;ans[171].z=-1328;
    ans[174].x=-170;ans[174].y=349;ans[174].z=-335;
    ans[177].x=-160;ans[177].y=1169;ans[177].z=-1168;
    ans[178].x=-10;ans[178].y=15;ans[178].z=-13;
    ans[179].x=1503;ans[179].y=2691;ans[179].z=-2839;
    ans[181].x=974;ans[181].y=4861;ans[181].z=-4874;
    ans[182].x=-29;ans[182].y=91;ans[182].z=-90;
    ans[183].x=976;ans[183].y=4876;ans[183].z=-4889;
    ans[186].x=5;ans[186].y=5;ans[186].z=-4;
    ans[187].x=-1092;ans[187].y=2000;ans[187].z=-1885;
    ans[188].x=318;ans[188].y=1635;ans[188].z=-1639;
    ans[189].x=-1403;ans[189].y=1974;ans[189].z=-1702;
    ans[190].x=-593;ans[190].y=4815;ans[190].z=-4812;
    ans[191].x=-215;ans[191].y=399;ans[191].z=-377;
    ans[192].x=16;ans[192].y=16;ans[192].z=-20;
    ans[196].x=-579;ans[196].y=1112;ans[196].z=-1057;
    ans[197].x=-1606;ans[197].y=3026;ans[197].z=-2867;
    ans[198].x=-1347;ans[198].y=3809;ans[198].z=-3752;
    ans[199].x=508;ans[199].y=2199;ans[199].z=-2208;
    ans[200].x=-638;ans[200].y=2334;ans[200].z=-2318;
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        if(ans[n].x==inf) printf("impossible\n");
        else printf("%d %d %d\n",ans[n].x,ans[n].y,ans[n].z);
    }
}

H. Yuuki and a problem
本题不带修版本来自codechef:https://www.codechef.com/problems/FRBSUM

带修时间复杂度会到O(nlogn^3),那么到1e9肯定就TLE了,但是此题太过于傻逼,出题人开了12s的时限

因子在原题的基础上再套个树,树套树即可。

#include
#include
#include
using namespace std;
typedef long long ll;
const int N=2e5+5;
int tot,x,y,n,m,a[N],rt[N<<2];
ll ans;
struct node
{
    int l,r;
    ll sum;
    node(){l=r=sum=0;}
}t[N*150];
int newnode()
{
    return ++tot;
}
void Insert(int l,int r,int x,int v,int &now)
{
    if(!now) now=newnode();
    t[now].sum+=v;
    if(l==r) return;
    int m=l+r>>1;
    if(x<=m) Insert(l,m,x,v,t[now].l);
    else Insert(m+1,r,x,v,t[now].r);
}
void fix(int l,int r,int k,int x,int v)
{
    Insert(1,n,v,x,rt[k]);
    if(l==r) return;
    int m=l+r>>1;
    if(x<=m) fix(l,m,k<<1,x,v);
    else fix(m+1,r,k<<1|1,x,v);
}
void del(int l,int r,int k,int x,int v)
{
    Insert(1,n,v,-x,rt[k]);
    if(l==r) return;
    int m=l+r>>1;
    if(x<=m) del(l,m,k<<1,x,v);
    else del(m+1,r,k<<1|1,x,v);
}
ll query(int l,int r,int x,int y,int now)
{
    if(!now||l>y||r<x) return 0;
    if(l>=x&&r<=y) return t[now].sum;
    int m=l+r>>1;
    return query(l,m,x,y,t[now].l)+query(m+1,r,x,y,t[now].r);
}
bool query(int l,int r,int k)
{
    ll sum=query(1,n,x,y,rt[k]);
    if(l==r)
    {
        if(l<=ans+1||sum==0)
        {
            ans+=sum;
            return true;
        }
        return false;
    }
    if(sum<=ans+1)
    {
        ans+=sum;
        return true;
    }
    int m=l+r>>1;
    if(query(l,m,k<<1)) return query(m+1,r,k<<1|1);
    return false;
}
int main()
{
    int tot=0;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        fix(1,200000,1,a[i],i);
    for(int i=1;i<=m;i++)
    {
        int opt;scanf("%d%d%d",&opt,&x,&y);
        if(opt==2)
        {
            ans=0;
            query(1,200000,1);
            printf("%lld\n",ans+1);
        }
        else
        {
            del(1,200000,1,a[x],x);
            a[x]=y;
            fix(1,200000,1,a[x],x);
        }
    }
}

L. Loli, Yen-Jen, and a cool problem
建立广义后缀自动机,在parent树上倍增跳父亲。

#include
using namespace std;
typedef long long ll;
const int N=6e5+5;
int n,m,num,lg[N],sum[N],ans[N],ep[N],ff[N],dep[N],head[N],nex[N],to[N];
int tot=1,las=1,fa[N][25],son[N][26],len[N];
void add(int u,int v){to[++num]=v;nex[num]=head[u];head[u]=num;}
char s[N];
int work(int p,int c)
{
    int nq=++tot,q=son[p][c];
    len[nq]=len[p]+1;
    fa[nq][0]=fa[q][0];fa[q][0]=nq;
    memcpy(son[nq],son[q],sizeof(son[q]));
    while(p&&son[p][c]==q) son[p][c]=nq,p=fa[p][0];
    return nq;
}
int ins(int p,int c)
{
    if(son[p][c])
    {
        int q=son[p][c];
        if(len[q]==len[p]+1) return q;
        return work(p,c);
    }
    int np=++tot;len[np]=len[p]+1;
    while(p&&!son[p][c]) son[p][c]=np,p=fa[p][0];
    if(!p) fa[np][0]=1;
    else
    {
        int q=son[p][c];
        if(len[q]==len[p]+1) fa[np][0]=q;
        else fa[np][0]=work(p,c);
    }
    return np;
}
void dfs(int u,int las)
{
    dep[u]=dep[ff[u]]+1;
    las=ins(las,s[u]-'A');
    ep[u]=las;sum[las]++;
    for(int i=head[u];i;i=nex[i])
    {
        int v=to[i];
        dfs(v,las);
    }
}
int vis[N];
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s",s+1);
    for(int i=2;i<=n;i++)
    {
        int p;scanf("%d",&p);
        ff[i]=p;add(p,i);
    }
    dfs(1,las);
    for(int i=1;i<=tot;i++)
        vis[fa[i][0]]++;
    queue<int>q;
    stack<int>s;
    for(int i=1;i<=tot;i++)
        if(!vis[i]) q.push(i);
    while(!q.empty())
    {
        int u=q.front();q.pop();s.push(u);
        ans[u]+=sum[u];
        ans[fa[u][0]]+=ans[u];
        vis[fa[u][0]]--;
        if(!vis[fa[u][0]]) q.push(fa[u][0]);
    }
    while(!s.empty())
    {
        int u=s.top();s.pop();
        for(int i=1;i<22;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    }
    while(m--)
    {
        int u,l;scanf("%d%d",&u,&l);
        l=min(l,dep[u]);
        u=ep[u];
        for(int j=21;j>=0;j--)
            if(len[fa[u][j]]>=l) u=fa[u][j];
        printf("%d\n",ans[u]);
    }
}

M. Kill the tree
拓扑排序一下,先处理完子树的答案,再处理父亲结点的答案。

假设当前点为u,它的一颗子树v的答案为ans[v],加入把ans[v]向父亲跳一格,那么所有在它上面的点的距离会减少1,它子树的距离会增加1

那么假设它父亲上的点的数量为up,它子树上的点为low,如果up>low,那么向父亲跳总距离就会减

因此up和low达到最均衡的状态,则使他们的差的绝对值最小的就是答案结点。

同时,当low==up的时候,这个时候答案有两个,因为往父亲跳距离减少up又加low,就是距离没变,所以这里特别判断一下就好了。

#include
using namespace std;
const int N=2e5+5;
int n,tot,si[N],dep[N],ans1[N],ans2[N],low[N],up[N],lev[N],fa[N],head[N],nex[N<<1],to[N<<1];
void add(int u,int v){to[++tot]=v;nex[tot]=head[u];head[u]=tot;}
stack<int>s;
void dfs(int u,int p)
{
    s.push(u);dep[u]=dep[p]+1;
    si[u]=1;fa[u]=p;
    lev[u]=1;
    for(int i=head[u];i;i=nex[i])
    {
        int v=to[i];if(v==p) continue;
        dfs(v,u);
        si[u]+=si[v];
        lev[u]=0;
    }
}
int jump(int u)
{
    int f=fa[u];
    up[f]=up[u]-si[f]+si[u];
    low[f]=si[f];
    return f;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int u,v;scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    dfs(1,0);
    while(!s.empty())
    {
        int u=s.top();s.pop();
        if(lev[u]) {low[u]=1;ans1[u]=u;continue;}
        for(int i=head[u];i;i=nex[i])
        {
            int v=to[i];if(v==fa[u]) continue;
            int t=ans1[v];
            if(ans2[v]) t=ans2[v];
            up[t]+=si[u]-si[v];
            while(up[t]>low[t]&&t!=u)
                t=jump(t);
            if(!ans1[u]||abs(low[t]-up[t])<abs(low[ans1[u]]-up[ans1[u]]))
            {
                ans1[u]=t;
                if(up[t]==low[t]&&t!=u)
                {
                    t=jump(t);
                    ans2[u]=t;
                }
            }
        }
    }
    for(int u=1;u<=n;u++)
        if(ans1[u]&&ans2[u])
        {
            if(ans1[u]>ans2[u]) swap(ans1[u],ans2[u]);
            printf("%d %d\n",ans1[u],ans2[u]);
        }
    else printf("%d\n",ans1[u]);
}

你可能感兴趣的:(2019 ICPC Asia Xuzhou Regional(A,C,E,F,H,L,M))