• Codeforces Round #572 (Div. 2)


    Codeforces Round #572 (Div. 2) 简要题解

    A. Keanu Reeves

    1. 0,1数目不相等表示满足条件,答案为1
    2. 相等,则从第一个字符分割即可

    B. Number Circle

    1. 排序,若满足(a[n]<a[n-1]+a[n-2]), 则可以构造,否则不可构造(这是显然的)
    2. 构造方法,假设(a[n])放在位置(k),则(a[n-1],a[n-2])放在(k-1,k+1),依次这样(a[i])成对枚举放在(k-t,k+t) 位置;注意环状和奇偶讨论即可

    C. Candies!

    1. (a_i+a_j<20) ,所以本质糖果数是区间和/10
    2. 前缀和处理即可

    D1. Add on a Tree

    1. 题意: 每次可对叶子节点x,y之间的简单路径上的边权进行同一操作(add val);问是否每条边权都能取任意值;即任意边不会存在互相约束;
    2. 结论: 存在度为2,则不可能(显然);反之可行(给出构造)
    3. 考虑叶子节点x和普通节点u,下面证明可以实现x-u路径上所有边加任意值(假设y);

    考虑u的子树(以u为根)的另外叶子节点(l_1,l_2),要求(l_1,l_2,x)不再(u)的同一个子树上。如下操作:
    (x-l_1 quad +y/2)
    (x-l_2 quad +y/2)
    (l_1-l_2 quad -y/2)
    即可实现x-u路径+y(可画图观察)

    1. 有3可知,对于v-u边的权值可通过 x-v和x-u进行3中的处理

    2. D1只需2即可解,但3,4两点对D2很有帮助

    D2. Add on a Tree: Revolution

    解法

    1. 如 D1所只,我们已经掌握了如何构造更改u-v边权的操作
    • 均为非叶子节点,转化为x-u,x-v 需要6次操作
    • 均为叶子节点(实际是两个节点的情况)
    • u位叶子节点,需要3次操作

    编程要点

    1. 至少需要获得非叶节点u的每个子树的一个叶子节点(以u为根);但一般dfs一次是固定的根
    2. 叶子节点x需要同时满足u,v的叶子节点,是u的v子树的叶子节点,而不是v的u子树叶子节点
    3. 自己的实现:
    • 以某一节点r为根求得非叶子节点的子树叶子节点集
    • 由于根的存在,某些非叶节点可能子树叶子节点集<3,那么从父节点的子树叶子节点集加入新的
    • 保证了至少有3个不同的叶子节点即很好处理了
    1. 下面是代码
    code
    #include <bits/stdc++.h>
    using namespace std;
    #pragma GCC optimize("O3")
    #define ll long long
    #define ull unsigned long long
    #define db(x) cout<<#x"=["<<(x)<<"]"<<endl
    #define CL(a,b) memset(a,b,sizeof(a))
    #define mp make_pair
    #define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define fr0(i,m) for(int i=0;i<m;i++)
    #define fr1(i,m) for(int i=1;i<=m;i++)
    //author:fridayfang
    //date:19 7月 06
    const double esp=1e-8;
    const int mod=1e9+7;
    const double pi=acos(-1);
    const int inf=0x3f3f3f3f;
    const int maxn = 1e3 + 5;
    const int maxm = 1e6+5;
    vector<pair<int,int>> G[maxn];//带权图
    vector<pair<pair<int,int>,int>> edgs;
    int par[maxn];//记录父亲
    bool vis[maxn];
    vector<int> leaf[maxn];//每次只选取子树的叶子节点leaf[]集的第一个
    vector<pair<pair<int,int>,int>> ops;//存储操作
    int n;
    int root;
    void dfs2(int u,int fa){
        par[u] = fa;
        if(G[u].size()==1){leaf[u].push_back(u);return ; }
        for(auto& tmp: G[u]){
            int t = tmp.first;
            if(t!=fa){dfs2(t,u);leaf[u].push_back(leaf[t][0]);}
        }
    }
    void pre(){
        dfs2(root,0);
        for(int i=1;i<=n;i++){
            if(G[i].size()>2&&leaf[i].size()==2){
                int u = par[i];
                for(auto& tmp: leaf[u]){
                    if(tmp!=leaf[i][0]&&tmp!=leaf[i][1]){
                        leaf[i].push_back(tmp);break;
                    }
                }
            }
        }
    }
    
    void addPath(int t,int v,int val){//表示对从t(v的某个叶子节点)-v 路径上全部加x
        int u = leaf[v][0], l1 = leaf[v][1], l2 = leaf[v][2];
        if(t==l1) swap(u,l1);// u=t
        if(t==l2) swap(u,l2);// u=t
        if(u!=t) swap(u,t);
        ops.push_back(mp(mp(u,l1),val/2));
        ops.push_back(mp(mp(u,l2),val/2));
        ops.push_back(mp(mp(l1,l2),-val/2));
    }
    void addEdge(int u,int v,int val){//对边u,v +x
        if(par[v]==u) swap(u,v);// keep v is father of u
        if(G[u].size()==1){addPath(u,v,val);return ;}
        if(G[v].size()==1){addPath(v,u,val);return ;}
        int t = leaf[u][0];
        addPath(t,v,val);
        addPath(t,u,-val);
    }
    void solve(){
        for(int i=1;i<=n;i++){
            root = i;
            dfs1(root,0);
        }
        for(int i=0;i<n-1;i++){
            int u = edgs[i].first.first, v = edgs[i].first.second, val = edgs[i].second;
            addEdge(u,v,val);
        }
        int opNum = ops.size();
        cout<<opNum<<endl;
        for(int i=0;i<opNum;i++){
            cout<<ops[i].first.first<<" "<<ops[i].first.second<<" "<<ops[i].second<<endl;
        }
    }
    
    
    
    int main(){
        fast();cin>>n;int u,v,val;
        if(n==2){
            cin>>u>>v>>val;
            cout<<"YES
    1
    "<<u<<" "<<v<<" "<<val<<endl;
            return 0;
        }
        for(int i=1;i<n;i++){
            cin>>u>>v>>val;
            G[u].push_back(mp(v,val)); G[v].push_back(mp(u,val));
            edgs.push_back(mp(mp(u,v),val));
        }
        bool OK = true; int j=-1;
        for(int i=1;i<=n;i++){
            if(G[i].size()==2) OK = false;
            if(G[i].size()>2) j = i;
        }
        if(!OK){cout<<"NO
    ";return 0;}
        if(j==-1){return 0;}// no reach
        cout<<"YES
    ";
        root = j; pre();
        solve();
    
    
    
        
        return 0;
    }
    

    E. Count Pairs

    1. 小技巧分离(i,j)即可,使得(i,j)同余;
    code
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define db(x) cout<<#x"=["<<(x)<<"]"<<endl
    #define CL(a,b) memset(a,b,sizeof(a))
    #define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define fr0(i,m) for(int i=0;i<m;i++)
    #define fr1(i,m) for(int i=1;i<=m;i++)
    //author:fridayfang
    //date:19 7月 06
    const double esp=1e-8;
    const int mod=1e9+7;
    const double pi=acos(-1);
    const int inf=0x3f3f3f3f;
    const int maxn = 3e5 + 5;
    const int maxm = 1e6+5;
    map<ll,ll> cnt;
    ll n,p,k;
    ll a[maxn];
    ll pre(ll x){
        ll t = x;
        x = (x*x)%p;
        x = (x*x)%p;
        x = (x+p-(k*t)%p)%p;
        return x;
    }
    ll solve(){
        ll ans = 0;
        for(ll i=1;i<=n;i++){
            ll t = pre(a[i]);
            ans = (ans+cnt[t]);
            cnt[pre(a[i])]++;
        }
        return ans;
    }
    
    int main(){
        fast();
        cin>>n>>p>>k;
        for(ll i=1;i<=n;i++)cin>>a[i];
        ll res = solve();
        cout<<res<<endl;
        
        return 0;
    }
    

    F. Array Beauty

    1. 题意很重要:(min_{1<=i<j<=n}{|a_i-a_j|}); 而不是(i,i+1)
    2. (q_i)(beauty>=i)的方案数;那么(sum{q_i})即为所求,因为(beauty==i)的方案被统计了(i)
    3. (dp[i][j])表述以(a[j])结尾的长度为i的方案数;具体见代码
    code
    #include <bits/stdc++.h>
    using namespace std;
    #pragma GCC optimize("O3")
    #define ll long long
    #define ull unsigned long long
    #define db(x) cout<<#x"=["<<(x)<<"]"<<endl
    #define CL(a,b) memset(a,b,sizeof(a))
    #define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define fr0(i,m) for(int i=0;i<m;i++)
    #define fr1(i,m) for(int i=1;i<=m;i++)
    //author:fridayfang
    //date:19 7月 06
    const double esp=1e-8;
    const int mod=998244353;
    const double pi=acos(-1);
    const int inf=0x3f3f3f3f;
    const int maxn = 1e3 + 5;
    const int maxm = 1e6+5;
    
    int a[maxn],n,k;
    int dp[maxn][maxn],tsum[maxn][maxn];
    //dp[i][j] 表示 长度为i以a[j]结尾的满足 beauty>=x 的 方案数
    //tsum[i][j] 表是dp[i][1]+dp[i][2]+....dp[i][j]
    int bound[maxn];// bound[i] = j 表示 a[i]...a[j] <= a[i]-x
    inline int add(int x,int y){return (x+y)>=mod?(x+y-mod):(x+y);}
    int solve(int x){//x>0
    /*
        for (int i = 0; i <= k; i++) {
            for (int j = 0; j <= n; j++) {
                dp[i][j] = 0;
            }
        }
        */
        bound[0] = 0;
        for(int i=1;i<=n;i++){
            bound[i] = bound[i-1];
            while(a[i]-a[bound[i]+1]>=x) bound[i]++;
        }
        tsum[1][0]=0;
        for(int i=1;i<=k;i++){
            for(int j=i;j<=n;j++){
                if(i==1){dp[i][j] = 1; tsum[i][j] = (tsum[i][j-1]+dp[i][j]); continue;}
                dp[i][j] = tsum[i-1][bound[j]];
               // printf("db dp[%d][%d]=%d
    ",i,j,dp[i][j]);
                tsum[i][j] = add(tsum[i][j-1],dp[i][j]);
            }
        }
        //db(tsum[k][n]);
        return tsum[k][n];
    }
    int main(){
        fast();cin>>n>>k;
        for(int i=1;i<=n;i++) cin>>a[i];
        sort(a+1,a+1+n);
        int ans = 0;
        int maxt = (a[n]-a[1])/(k-1);
        for(int t=1;t<=maxt;t++){
            ans = add(ans, solve(t));
        }
        cout<<ans<<endl;
        
        return 0;
    }
    
  • 相关阅读:
    Probability theory
    python Memo
    numpy 札记
    linux LVM 逻辑卷
    关于TF-IDF的一些见解
    Python之list、dict、np等常用数值运算
    Python之matplotlib绘图
    Python之打开网页
    Python之获取地址经纬度
    两台电脑直接共享文件
  • 原文地址:https://www.cnblogs.com/fridayfang/p/11144930.html
Copyright © 2020-2023  润新知