Codeforces Round#636(Div。3)Supplement


A.キャンディーと他の
比率シーケンスを合計して、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.バランスドアレイ
は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.代替
サブシーケンスは、指定されたシーケンスが負の数と正の数のシーケンスであることと同等です。各負の部分と各正の部分から数を選択するには、新しい系列を作成し、この系列の合計を最大にします。 。この方法では、各パーツで最大の数を選択するだけで済みます。

コード

#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.一定のパリンドロームの合計
各ログとその合計について、cnt配列を使用して合計の発生数を格納できます。また、ログは1つの要素で取得できる合計の範囲のみを変更し、差分配列を使用することもわかります。 Prefは、この範囲の上限と下限を格納するために使用されます。すべての数値を数えた後、差分配列はプレフィックスを合計して、特定のxに対して1回しか操作できない数値グループの数を把握します。すべての可能なxを列挙するには、対応する答えは、xの対数を1回未満取得し、xの対数を減算し、さらに2倍の演算を2回実行してxの対数を取得することです。合計ログからxの対数を差し引いた値が1以下の操作は、2つの操作後の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.重み付け
最初にbfsを使用してbfsを使用し、abcを開始点として最短経路を前処理し(各道路の長さは1と見なされ、取得する道路の数)、道路のコストを小から大に分類します。中間点xを見つけて、行く方向がa——x——b——x——cになるようにします。このxは、bにすることもできます。各xについて、行く最も短い方法の数を数えます。 aからxがm道路を、xからbがn道路を、xからcがq道路をとる場合、nを最初のn個の小さなコストに対応させることができます(2回歩く必要があるため)、残りの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.並べ替えられたセグメントによる順列の復元
入力は、可変長rの2〜n個の要素をすべて与えます。配列の最初の数値を列挙し、それがfstであると仮定し、fstを含むすべてのフラグメントのfstを削除すると、2番目の要素がrであるフラグメントに1つの要素、つまり[2]が残り、次に[2]を含むすべてのフラグメントの[2]を削除すると、[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