Codeforces Round #636 (Div. 3) 补题


A. Candies
等比数列求和之后得到k和x的式子,枚举k即可,因为是幂函数,k并不会很大

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    read(q);
    while(q--){
        int n;
        cin>>n;
        ll k,ans;
        for(k=2;;k++){
            ll cnt=(1<<k)-1;
            if(n%cnt==0){
                ans=n/cnt;break;
            }
        }
        cout<<ans<<endl;
    }
 	return 0;
}
 

B. Balanced Array
只要n能整除4即可
我的构造是偶数部分都输出2i,奇数部分前一半输出2i-1,后一半输出2i+1

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    cin>>q;
    while(q--){
        int n;
		cin>>n;
		n/=2;
		if(n%2){
			printf("NO\n");
			
		}
		else{
			printf("YES\n");
			for(int i=1;i<=n;i++) cout<<2*i<<" ";
			for(int i=1;i<=n;i++){
				if(i<=n/2) cout<<2*i-1<<" ";
				else cout<<2*i+1<<" ";
			}
			cout<<"\n";
		}
    }
 	return 0;
}
 

C. Alternating Subsequence
题意相当于给的数列是负数数列和正数数列交替,要从每个负数部分和每个正数部分都选出一个数,来构造一个新的数列,让这个数列的和最大。这样只需要在每个部分都选最大的那个数就好了

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    cin>>q;
    while(q--){
        int n;
		cin>>n;
		vector<int> a(n+1);
		for(int i=1;i<=n;i++) {cin>>a[i];}
		ll ans=0;
		ll pre=a[1],now=1234567890;
		for(int i=1;i<=n;i++){
			now=a[i];
			if(pre>0&&now>0){
				now=max(pre,now);
				pre=now;
			}
			else if(pre<0&&now<0){
				now=max(pre,now);
				pre=now;
			}
			else{
				ans+=pre;
				pre=now;
			}
		}
		ans+=pre;
		cout<<ans<<endl;
    }
 	return 0;
}
 

D. Constant Palindrome Sum
对于每一对数,和他们的和sum,我们可以用cnt数组存储sum出现的次数,还可以知道这对数只改变一个元素所能得到的sum的范围,用一个差分数组pref来存储这个范围的上下界,统计完所有数后,差分数组求前缀和就能知道对于某个x,有多少组数可以操作不超过1次得到x。枚举所有可能的x,对应的答案就是操作不超过1次能得到x的对数减去和已经是x的对数,再加上2乘以操作两次才能得到x的对数。其中总对数减去操作不超过1次能得到x的对数就是操作两次才能得到x的对数。

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
vector<int> a;
map<int,int> cnt,pref;
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    read(q);
    while(q--){
        int n,k;
        cin>>n>>k;
        a.resize(n);
        cnt.clear(),pref.clear();
        for(auto &x:a) read(x);
        for(int i=0;i<n/2;i++) cnt[a[i]+a[n-i-1]]++;
        for(int i=0;i<n/2;i++){
            int l=a[i],r=a[n-i-1];
            pref[max(l,r)+k+1]--;
            pref[min(l,r)+1]++;
        }
        for(int i=2;i<=2*k;i++){
            pref[i]+=pref[i-1];
        }
        int ans=99999999;
        for(int i=2;i<=2*k;i++){
            ans=min(ans,pref[i]-cnt[i]+2*(n/2-pref[i]));
        }
        cout<<ans<<"\n";
    }
 	return 0;
}
 

E. Weights Distributing
先分别用bfs预处理abc为起点的最短路(每条路长度视为1,要走的路的数量),并把路的花费从小到大排序。寻找一个中介点x,使要走的路变成a——x——b——x——c,这个x也可以是b,统计出每个x对应的要走的最少的路的数量,如果a到x要走m条路,x到b要走n条路,x到c要走q条路,那么可以让n对应前n小的花费(因为要走两遍),剩下的m+p条路对应前n+1到m+p小的花费,就可以得到对应的最小花费。遍历x更新最小值即可。

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
vector<vector<int> > mp;
void bfs(int a,vector<int> & d){
    queue<int> q;
    q.push(a);
    d[a]=0;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(auto i:mp[x]){
            if(d[i]!=INF) continue;
            d[i]=d[x]+1;
            q.push(i);
        }
    }
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    read(q);
    while(q--){
        int n,m,a,b,c;
        cin>>n>>m>>a>>b>>c;
        vector<int> p(m);
        for(auto &x:p) read(x);
        sort(p.begin(),p.end());
        mp=vector<vector<int> >(n);
        for(int i=0;i<m;i++){
            int x,y;
            read(x),read(y);
            x--;y--;
            mp[x].push_back(y);
            mp[y].push_back(x);
        }
        a--;b--;c--;
        vector<int> aa(n,INF),bb(n,INF),cc(n,INF);
        bfs(a,aa);
        bfs(b,bb);
        bfs(c,cc);
        vector<ll> d(m+1);
        for(int i=1;i<=m;i++) d[i]=d[i-1]+p[i-1];
        ll ans=1e18;
        for(int i=0;i<n;i++){
            if(aa[i]+bb[i]+cc[i]>m) continue;
            ans=min(ans,d[aa[i]+bb[i]+cc[i]]+d[bb[i]]);
        }
        cout<<ans<<"\n";
    }
 	return 0;
}
 

F. Restore the Permutation by Sorted Segments
输入中给出了所有2到n个元素为r的不定长度片段。枚举数组中第一个数,假设为fst,所有含有fst到片段中都删去fst,那么以第二个元素为r的片段中就会剩下一个元素,即a[2],再把所有含a[2]的片段都删去a[2],就能得到a[3],重复这样的操作就能得到所有的元素。求出来一个可能符合的数组后要检验一下是否满足输入所给的n-1个片段。这些片段用set维护较为方便。

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long int ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-'0';c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    int q;
    read(q);
    while(q--){
        int n;
        read(n);
        vector<set<int> > segs;
        for(int i=0;i<n-1;i++){
            int k;
            read(k);
            set<int> seg;
            for(int i=0;i<k;i++){
                int x;
                read(x);
                seg.insert(x);
            }
            segs.push_back(seg);
        }
        for(int fst=1;fst<=n;fst++){
            bool flag=true;
            vector<int> ans;
            vector<set<int> > cur=segs;
            for(auto & x:cur){
                if(x.count(fst)){
                    x.erase(fst);
                }
            }
            ans.push_back(fst);
            for(int i=1;i<n;i++){
                int num=0;
                int nxt=-1;
                for(auto &x:cur){
                    if(x.size()==1){
                        ++num;
                        nxt=*x.begin();
                    }
                }
                if(num!=1){
                    flag=false;
                    break;
                }
                for(auto & x:cur){
                    if(x.count(nxt)){
                        x.erase(nxt);
                    } 
                }
                ans.push_back(nxt);
            }
            //check
            if(flag){
                set<set<int> > all(segs.begin(),segs.end());
                for(int i=1;i<n;i++){
                    set<int> seg;
                    seg.insert(ans[i]);
                    bool ok=false;
                    for(int j=i-1;j>=0;j--){
                        seg.insert(ans[j]);
                        if(all.count(seg)){
                            ok=true;
                            break;
                        }
                    }
                    if(!ok){
                        flag=false;
                        break;
                    }
                }
            }
            if(flag){
                for(auto x:ans){
                    cout<<x<<" ";
                }putchar('\n');
                break;
            }
        }
    }
 	return 0;
}
 
 

猜你喜欢

转载自www.cnblogs.com/DinoMax/p/12757996.html