Codeforces Gym 102059 部分题题解

(具体题解慢慢完善)

A.Coloring Roads

题目链接

Coloring Roads

简要题解

这道题看起来挺可做,因为约束条件挺强的,每次都是染色从某个点到根的一条路径。
不如做一个大胆猜想:每次需要修改的路径上均摊只有大约\(logn\)种不同的颜色。

既然是维护树上路径,我们不难想到树链剖分。
将轻重链划分之后,每条重链维护一个单调栈,栈内存的是这条重链上的颜色段,栈顶到栈底的颜色深度单增。
对于每次修改,我们跳重链,每到一条重链,就把栈内小于当前点深度的颜色全部弹掉,然后把当前点的颜色和深度加入栈内。
修改栈的过程中,直接用桶维护每种颜色有几条链,以及含有几条链的颜色有几种。
分析一下,每次修改最多给栈内加入\(logn\)个元素,因此弹栈和入栈的总次数是\(O(n*logn)\)级别的,树链剖分每次也是\(logn\)级别的
总时间复杂度为\(O(n*logn)\)
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
struct EDGE{   int u,v,Next;   }Edge[MAXN*2];
int n,C,Qs,Es,First[MAXN];
int Tong[MAXN],Cnt[MAXN];
int Read()
{   int a=0,c=1;   char b=getchar();
    while(b!='-'&&(b<'0'||b>'9')) b=getchar();
    if(b=='-') c=-1,b=getchar();
    while(b>='0'&&b<='9') a=a*10+b-48,b=getchar();
    return a*c;
}
void Link(int u,int v){   Edge[++Es]=(EDGE){u,v,First[u]},First[u]=Es;   }
void Add(int Nc,int Num){   Tong[Cnt[Nc]]--,Cnt[Nc]+=Num,Tong[Cnt[Nc]]++;   }
namespace Heavy
{   struct ELE{   int C,D;   };
    int Ds,Dfn[MAXN],Tot[MAXN],Son[MAXN],Old[MAXN],Top[MAXN],Fa[MAXN],Deep[MAXN];
    stack<ELE>Stk[MAXN];
    void Dfs1(int Now,int Ba)
    {   Tot[Now]=1,Fa[Now]=Ba,Deep[Now]=Deep[Ba]+1;
        for(int i=First[Now],v;i!=-1;i=Edge[i].Next)
        {   if((v=Edge[i].v)==Ba) continue ;
            Dfs1(v,Now),Tot[Now]+=Tot[v];
            if(Tot[v]>Tot[Son[Now]]) Son[Now]=v;
        }
    }
    void Dfs2(int Now,int Topf)
    {   Dfn[Now]=++Ds,Top[Ds]=Topf;
        if(Son[Now]) Dfs2(Son[Now],Topf);
        for(int i=First[Now],v;i!=-1;i=Edge[i].Next)
            if((v=Edge[i].v)!=Fa[Now]&&v!=Son[Now]) Dfs2(v,Ds+1);
    }
    void Modify(int Bot,int Nc)
    {   int Nt=0,Nd;
        for(Bot=Dfn[Bot];Bot!=1;Bot=Dfn[Fa[Old[Top[Bot]]]])
        {   Nt=Top[Bot]+(Top[Bot]==1),Nd=Deep[Old[Nt]]-1;
            for(ELE Up;!Stk[Nt].empty();)
            {   Up=Stk[Nt].top();
                if(Up.D<=Deep[Old[Bot]]) Add(Up.C,Nd-Up.D),Nd=Up.D,Stk[Nt].pop();
                else
                {   Add(Up.C,Nd-Deep[Old[Bot]]);
                    break ;
                }
            }
            Stk[Nt].push((ELE){Nc,Deep[Old[Bot]]}),Add(Nc,Deep[Old[Bot]]-Deep[Old[Nt]]+1);
        }
    }
}using namespace Heavy;
int main()
{   n=Read(),C=Read(),Qs=Read(),Tong[0]=C;
    memset(First,-1,sizeof(First));
    for(int i=1,A,B;i<=n-1;i++) A=Read(),B=Read(),Link(A,B),Link(B,A);
    Dfs1(1,1),Dfs2(1,1);
    for(int i=1;i<=n;i++) Old[Dfn[i]]=i;
    for(int i=1,A,B,C;i<=Qs;i++) A=Read(),B=Read(),C=Read(),Modify(A,B),printf("%d\n",Tong[C]);
}

D.Dumae

题目链接

Dumae

简要题解

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+10;
struct ELE{   int Id,Ri;   }Top;
struct SEC{   int Le,Ri;   }Sec[MAXN];
int n,m,Os,Ord[MAXN],Deg[MAXN],Ans[MAXN];
vector<int>Aft[MAXN];
vector<ELE>Seq[MAXN];
queue<int>Team;
priority_queue<ELE>Heap;
int Read()
{   int a=0,c=1;   char b=getchar();
    while(b!='-'&&(b<'0'||b>'9')) b=getchar();
    if(b=='-') c=-1,b=getchar();
    while(b>='0'&&b<='9') a=a*10+b-48,b=getchar();
    return a*c;
}
int Min(int A,int B){   return A<B?A:B;   }
int Max(int A,int B){   return A>B?A:B;   }
bool operator <(ELE A,ELE B){   return A.Ri>B.Ri;   }
void Toposort()
{   for(int i=1;i<=n;i++)
        if(!Deg[i]) Team.push(i);
    for(int Now;!Team.empty();)
    {   Now=Team.front(),Team.pop(),Ord[++Os]=Now;
        for(int v:Aft[Now])
            if((--Deg[v])==0) Team.push(v);
    }
    if(Os<n) puts("-1"),exit(0);
}
void Solve()
{   for(int i=n,Now;i>=1;i--)
    {   Now=Ord[i];
        for(int v:Aft[Now]) Sec[Now].Ri=Min(Sec[Now].Ri,Sec[v].Ri-1);
    }
    for(int i=1,Now;i<=n;i++)
    {   Now=Ord[i];
        for(int v:Aft[Now]) Sec[v].Le=Max(Sec[v].Le,Sec[Now].Le+1);
    }
    for(int i=1;i<=n;i++) Seq[Sec[i].Le].push_back((ELE){i,Sec[i].Ri});
    for(int i=1;i<=n;i++)
    {   for(ELE j:Seq[i]) Heap.push(j);
        if(Heap.empty()) puts("-1"),exit(0);
        Top=Heap.top(),Heap.pop();
        if(Top.Ri<i) puts("-1"),exit(0);
        Ans[i]=Top.Id;
    }
}
int main()
{   n=Read(),m=Read();
    for(int i=1;i<=n;i++) Sec[i].Le=Read(),Sec[i].Ri=Read();
    for(int i=1,A,B;i<=m;i++) A=Read(),B=Read(),Aft[A].push_back(B),Deg[B]++;
    Toposort(),Solve();
    for(int i=1;i<=n;i++) printf("%d\n",Ans[i]);
}

E.Electronic Circuit

题目链接

Electronic Circuit

简要题解

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
int n,m,Ans,Vis[MAXN];
set<int>Edge[MAXN];
queue<int>Team;
int Read()
{   int a=0,c=1;   char b=getchar();
    while(b!='-'&&(b<'0'||b>'9')) b=getchar();
    if(b=='-') c=-1,b=getchar();
    while(b>='0'&&b<='9') a=a*10+b-48,b=getchar();
    return a*c;
}
void Bfs()
{   for(int i=1;i<=n;i++)
        if(Edge[i].size()==2) Team.push(i),Vis[i]=1;
    for(int Now,A,B;!Team.empty();)
    {   Now=Team.front(),Team.pop();
        if(Edge[Now].size()!=2) continue ;
        A=*Edge[Now].begin(),Edge[A].erase(Now),B=*Edge[Now].rbegin();
        Edge[B].erase(Now),Edge[A].insert(B),Edge[B].insert(A),Edge[Now].clear();
        if(Edge[A].size()==2&&!Vis[A]) Team.push(A),Vis[A]=1;
        if(Edge[B].size()==2&&!Vis[B]) Team.push(B),Vis[B]=1;
    }
}
int main()
{   n=Read(),m=Read();
    for(int i=1,A,B;i<=m;i++) A=Read(),B=Read(),Edge[A].insert(B),Edge[B].insert(A);
    Bfs();
    for(int i=1;i<=n;i++)
        if(Edge[i].size()>1) return puts("No");
        else Ans+=(Edge[i].size()==1);
    puts(Ans==2?"Yes":"No");
}

F.Fake Plastic Trees

题目链接

Fake Plastic Trees

简要题解

代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n;
int T,Ans,Ts,Lson[1010],Rson[1010];
map<ll,int>Map;
int Build(ll Num)
{   if(Map.find(Num)!=Map.end()) return Map[Num];
    ll Hf=Num/2,Nr=Build(Hf),Nl=Build(Num-Hf),Nd=++Ts;
    return Lson[Nd]=Nl,Rson[Nd]=Nr,Map[Num]=Nd;
}
int main()
{   for(scanf("%d",&T);T;T--)
    {   scanf("%lld",&n),Ts=0,Map.clear(),Map[1]=0,Lson[0]=Rson[0]=-1;
        Ans=Build(n),printf("%d\n",Ts+1);
        for(int i=0;i<=Ts;i++) printf("%d %d\n",Lson[i],Rson[i]);
        printf("%d\n",Ans);
    }
}

G.Fascination Street

题目链接

Fascination Street

简要题解

代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=25e4+10;
const ll Inf=1e18;
int n,K,W[MAXN];
ll Ans=Inf,F[MAXN][11][11][4];
int Read()
{   int a=0,c=1;   char b=getchar();
    while(b!='-'&&(b<'0'||b>'9')) b=getchar();
    if(b=='-') c=-1,b=getchar();
    while(b>='0'&&b<='9') a=a*10+b-48,b=getchar();
    return a*c;
}
ll Min(ll A,ll B){   return A<B?A:B;   }
int main()
{   n=Read(),K=Read();
    memset(F,0X7f,sizeof(F));
    for(int i=1;i<=n;i++) W[i]=Read();
    F[0][0][0][2]=0;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=K;j++)
            for(int k=0;k<=K;k++)
                for(int l=0,St;l<=3;l++)
                {   if(l)
                    {   St=l<<1&3,F[i][j][k][St]=Min(F[i][j][k][St],F[i-1][j][k][l]);
                        F[i][j+1][k][St]=Min(F[i][j+1][k][St],F[i-1][j][k][l]+W[i]);
                    }
                    St=l<<1&3|1,F[i][j][k][St]=Min(F[i][j][k][St],F[i-1][j][k][l]+W[i]);
                    F[i][j][k+1][St]=Min(F[i][j][k+1][St],F[i-1][j][k][l]);
                }
    for(int i=0;i<=K;i++)
        for(int j=1;j<=3;j++) Ans=Min(Ans,F[n][i][i][j]);
    printf("%lld\n",Ans);
}

I.Game on Plane

题目链接

Game on Plane

简要题解

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5010;
int T,n,SG[MAXN],Get[MAXN];
int main()
{   for(int i=2;i<=5000;i++)
    {   for(int j=0,k=i-2;j<=k;j++,k--) Get[SG[j]^SG[k]]=1;
        for(int j=0;j<=5000;j++)
            if(!Get[j]) SG[i]=j,j=5000;
        for(int j=0,k=i-2;j<=k;j++,k--) Get[SG[j]^SG[k]]=0;
    }
    for(scanf("%d",&T);T;T--)
        scanf("%d",&n),puts(SG[n]?"First":"Second");
}

M.Utilitarianism

题目链接

Utilitarianism

简要题解

代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=25e4+10;
const ll Inf=1e18;
struct EDGE{   int u,v,Next;   ll w;   }Edge[MAXN*2];
int n,K,Es,Get,First[MAXN],Fs[MAXN][2];
ll Ans,F[MAXN][2];
int Read()
{   int a=0,c=1;   char b=getchar();
    while(b!='-'&&(b<'0'||b>'9')) b=getchar();
    if(b=='-') c=-1,b=getchar();
    while(b>='0'&&b<='9') a=a*10+b-48,b=getchar();
    return a*c;
}
ll Max(ll A,ll B){   return A>B?A:B;   }
void Link(int u,int v,ll w){   Edge[++Es]=(EDGE){u,v,First[u],w},First[u]=Es;   }
void Trans(ll &N0,int &Ns0,ll &N1,int &Ns1,ll &V0,int &Vs0,ll &V1,int &Vs1,ll &w)
{   ll B;   int Bs;
    if(V0==V1) B=V0,Bs=Max(Vs0,Vs1);
    else V0>V1?(B=V0,Bs=Vs0):(B=V1,Bs=Vs1);
    N1+=B,Ns1+=Bs;
    if(N1<N0+V0+w) N1=N0+V0+w,Ns1=Ns0+Vs0+1;
    else if(N1==N0+V0+w&&Ns1<Ns0+Vs0+1) Ns1=Ns0+Vs0+1;
    N0+=B,Ns0+=Bs;
}
void Dfs(int Now,int Ba)
{   for(int i=First[Now],v;i!=-1;i=Edge[i].Next)
    {   if((v=Edge[i].v)==Ba) continue ;
        Dfs(v,Now),Trans(F[Now][0],Fs[Now][0],F[Now][1],Fs[Now][1],F[v][0],Fs[v][0],F[v][1],Fs[v][1],Edge[i].w);
    }
}
int Check(ll Rate)
{   for(int i=1;i<=Es;i++) Edge[i].w-=Rate;
    for(int i=1;i<=n;i++) F[i][0]=0,F[i][1]=-Inf,Fs[i][0]=Fs[i][1]=0;
    Dfs(1,1);
    for(int i=1;i<=Es;i++) Edge[i].w+=Rate;
    return F[1][0]<F[1][1]?Fs[1][1]>=K:Fs[1][0]>=K;
}
int main()
{   n=Read(),K=Read();
    memset(First,-1,sizeof(First));
    for(int i=1,u,v,w;i<n;i++) u=Read(),v=Read(),w=Read(),Link(u,v,w),Link(v,u,w);
    for(ll Le=-1e12,Ri=1e12,Mid;Le<=Ri;)
        Mid=(Le+Ri)/2,Check(Mid)?(Ans=Max(F[1][0],F[1][1])+Mid*K,Get=1,Le=Mid+1):Ri=Mid-1;
    Get?printf("%lld\n",Ans):puts("Impossible");
}
posted @ 2021-08-13 22:55  Alkaid~  阅读(106)  评论(0编辑  收藏  举报