Codeforces Round #636 (Div. 3)

A. Candies

题意

求出任意一个x,满足\(x+2x+4x+⋯+2^{k−1}x=n.\),k为任意大于1的数。\((3≤n≤10^9)\)

思路

将2的指数的前缀和大表存在Map,然后枚举k,只需要枚举1到sqrt(n)即可。

代码

#include<bits/stdc++.h>
using namespace std;
map<long long,int> mmp;
int main(){
    int T;
    long long p=1,sum=0;
    for(int i=1;i<=32;++i){
        sum+=p;
        mmp[sum]=i;
        p*=2;
    }
    mmp[1]=0;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        for(int i=1;i<=sqrt(n);++i){
            if(n%i==0&&mmp[n/i]){
                cout<<i<<endl;
                break;
            }
            else if(n%i==0&&mmp[i]){
                cout<<n/i<<endl;
                break;
            }
        }
    }
    return 0;
}

B. Balanced Array

题意

构造一个长度为n的序列满足:前n/2个数字是偶数,后n/2个数字是奇数,且前n/2个数之和等于后n/2个数之和。\((2≤n≤2⋅105)\)

思路

假设让前n/2个数等于2到n之间的偶数,后n/2-1个数等于1到n之间的奇数,将前后的差补在最后一个数上,使得最后一个数是奇数,否则输出“NO”.

代码

#include<bits/stdc++.h>
using namespace std;
int a[200010];
int main(){
    int T;
    cin>>T;
    int t=2;
    for(int i=1;i<=100000;++i,t+=2){
        a[i]=t;
    }
    t=1;
    for(int i=100001;i<=200000;++i,t+=2){
        a[i]=t;
    }
    while(T--){
        int n;
        cin>>n;
        if((n/2)%2){
            cout<<"NO\n";
            continue;
        }
        cout<<"YES\n";
        for(int i=1;i<=n/2;++i){
            cout<<a[i]<<" ";
        }
        for(int i=100001;i<=100000+n/2;++i){
            if(100000+n/2==i){
                cout<<a[i]+n/2;
            }
            else cout<<a[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

C. Alternating Subsequence

题意

给出一个只有正负数的序列,求出最长的摆动子序列(正负交替),在子序列最长的前提下,子序列之和尽可能地大。\((1≤n≤2⋅105)\)

思路

模拟:对正负性相同的连续一段选出值最大的一个加入到序列中去。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL f[200010][2],a[200010];
int main(){
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        LL ans=0;
        for(int i=1;i<=n;){
            LL tmp=-1e18;
            int j=i;
            for(;j<=n;++j){
                if(a[i]*a[j]>=0){
                    tmp=max(a[j],tmp);
                }
                else break;
            }
            i=j;
            ans+=tmp;
        }
        cout<<ans<<endl;
    }
    return 0;
}

D. Constant Palindrome Sum

题意

将一个序列的某一个数字替换成1到k的任意一个数,使得最终的序列满足对于所有的\(i∈(1,n/2)\)有:\(ai+an−i+1=x\)\((2≤n≤2⋅10^5,1≤k≤2⋅10^5,1≤ai≤k)\)

思路

x可以等于2到2k之间的任意一个数,那么我们枚举每个二元组,求出不改变时它可以取到的和,改变一个可以取到的和,改变两个可以取到的和各有哪些。
那么对于可以取到的值去差分,最后求出最小的一个值,就是操作次数最少可以得到的x。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int t[200010],n,m;
int f[1000010];
signed main(){
    int T;
    cin>>T;
    while(T--){
        cin>>n>>m;
        for(int i=0;i<=2*m;++i){
            f[i]=0;
        }
        for(int i=1;i<=n;++i){
            cin>>t[i];
        }
        for(int i=1;i<=n/2;++i){
            int a=t[i],b=t[n-i+1];
            int l1=b+1,r1=b+m;
            int l2=a+1,r2=a+m;
            f[min(l1,l2)]++;
            f[a+b]--;
            f[a+b+1]++;
            f[max(r1,r2)+1]--;
            f[2]+=2;
            f[min(l1,l2)]-=2;
            f[max(r1,r2)+1]+=2;
            f[2*m+1]-=2;
        }
        int ans=1000000;
        for(int i=2;i<=m*2;++i){
            f[i]+=f[i-1];
            ans=min(ans,f[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

E. Weights Distributing

题意

在一个暂未赋权有m条边的无向图的和m个权值,求出存在有一种赋权的最优方案从a到b到c的最小花费。

思路

一定只有两种路线即:

  1. a -> v -> b -> v -> c,即从a到v到b再折返回v到c。
  2. a -> b -> c,即从a到b到c没有走重边,那么也可以变形为:a -> b -> b -> b -> c。

预处理a,b,c到每个点经过的最少边数,再将p排序求出前缀和。由于b到v的过程走了两次,所以a到b的边权尽可能地小,再取a到v和c到v的边权。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int h[N],idx;
typedef long long LL;
LL p[N*2];
int d1[N],d2[N],d3[N],q[N];
struct eg{
    int v,nex;
}e[N*2];
void add(int u,int v){
    e[idx]={v,h[u]};
    h[u]=idx++;
}
void bfs(int d[],int S){
    int hh=0,tt=0;
    q[tt++]=S;
    d[S]=0;
    while(hh!=tt){
        int u=q[hh++];
        if(hh==N) hh=0;
        for(int i=h[u];~i;i=e[i].nex){
            int v=e[i].v;
            if(d[v]>d[u]+1){
                d[v]=d[u]+1;
                q[tt++]=v;
                if(tt==N) tt=0;
            }
        }
    }
}
int main(){
    int T;
    cin>>T;
    while(T--){
        memset(h,-1,sizeof h);idx=0;
        memset(d1,0x3f,sizeof d1);
        memset(d2,0x3f,sizeof d2);
        memset(d3,0x3f,sizeof d3);
        int n,m,a,b,c;
        cin>>n>>m>>a>>b>>c;
        for(int i=1;i<=m;++i)   cin>>p[i];
        sort(p+1,p+1+m);
        for(int i=1;i<=m;++i) p[i]+=p[i-1];
        for(int i=1;i<=m;++i){
            int u,v;
            cin>>u>>v;
            add(u,v);
            add(v,u);
        }
        bfs(d1,a);
        bfs(d2,b);
        bfs(d3,c);
        LL ans=1e18;
        for(int i=1;i<=n;++i){
            int t1=d2[i],t2=d1[i]+d3[i];
            if(t1+t2<=m){
                ans=min(ans,p[t1]*2+p[t1+t2]-p[t1]);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
posted @ 2020-04-22 16:34  0x4f  阅读(121)  评论(0编辑  收藏  举报