Codeforces Round #595 (Div. 3)

A

對數組排序,如果存在相鄰兩項爲1,則最少可以分成兩組,否則分成1組。

#include<bits/stdc++.h>
 
using namespace std;
int a[200];
int main(){
    int T;
    cin>>T;
    while(T--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        sort(a+1,a+n+1);
        int res=0;
        for(int i=2;i<=n;i++){
            if(a[i]-a[i-1]==1) res++;
        }
        if(res) cout<<2<<endl;
        else cout<<1<<endl;
    }
    return 0;
}

B1&B2

整個問題可以轉化爲一個圖求各個環的大小的問題,由於每個點只會在一個環中出現,考慮DSUDSUTarjanTarjan 求環即可。
時間複雜度O(n)O(n)

#include<bits/stdc++.h>
 
using namespace std;
const int N = 2e5+100;
vector<int> G[N];
bool is_instack[N];
int dfn[N],low[N],siz[N],color[N],a[N];
stack<int> sta;
int n,m,idx,scc;
void init(int n){
	idx=scc=0;
	for(int i=0;i<=n;i++) dfn[i]=low[i]=is_instack[i]=color[i]=siz[i]=0;
	while(!sta.empty()) sta.pop();
	for(int i=0;i<=n;i++) G[i].clear();
}
void Tarjan(int u){
	low[u]=dfn[u]=++idx;
	is_instack[u]=1;sta.push(u);
	for(int v:G[u]){
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(is_instack[v]){
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(low[u]==dfn[u]){
		scc++;
		while(1){
			int temp=sta.top();
			color[temp]=scc;
            siz[scc]++;
			is_instack[temp]=0;
			sta.pop();
			if(temp==u) break;
		}
	}
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        init(n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            G[i].push_back(a[i]);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]) Tarjan(i);
        }
        for(int i=1;i<=n;i++){
            printf("%d ",siz[color[i]]);
        }
        puts("");
    }
    return 0;
}

C1&C2

goodnumbergood number的本質即爲三進制下各位都不是22的數字,因此對於nn,在三進制下找到22最左邊的00然後變爲11,後面的全部變爲00即可。複雜度O(Tlog3(n))O(T*log_3(n))

#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
string change(ll x){
    if(x==0) return "0";
    string res="";
    while(x){
        res+=char(x%3+'0');
        x/=3;
    }
    res+="0";
    reverse(res.begin(),res.end());
    return res;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int T;
    cin>>T;
    while(T--){
        ll n;
        cin>>n;
        string now=change(n);
        // cout<<n<<" base3 "<<now<<endl;
        bool f=0;
        for(char v:now){
            if(v=='2') f=1;
        }
        if(!f){
            cout<<n<<endl;continue;
        }
        int len=(int)now.length();
        ll ans=0;
        int id;
        for(int i=0;i<len;i++){//找到第一個2
            if(now[i]=='2'){
                id=i;break;
            }
        }
        int id2;
        for(int i=id;i>=0;i--){//找到離2最近的0
            if(now[i]=='0'){
                id2=i;
                 now[i]='1';break;
            }
        }
        for(int i=id2+1;i<len;i++) now[i]='0';//後面全爲0
        for(char c:now){
            ans=ans*3+(c-'0');
        }
        cout<<ans<<endl;
    }
    return 0;
}

D1&D2

考慮貪心:每次選取最左邊的被線段覆蓋超過kk次的點,按照右端點從大到小刪除覆蓋該點的線段,依次模擬即可。
可以考慮使用setset,時間複雜度O(nlog(n))O(nlog(n))

#include<bits/stdc++.h>
 
using namespace std;
const int N = 2e5+100;
vector<pair<int,int> > seg[N];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);    
    int n,k,l,r;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>l>>r;
        seg[l].push_back({r,i});
    }
    vector<int> del;
    set<pair<int,int> > q;
    for(int i=0;i<=2e5+1;i++){
        for(auto v:seg[i]){
            q.insert(v);
        }
        while(q.size()>k){
            del.push_back(q.rbegin()->second);
            q.erase(*q.rbegin());
        }
        while(!q.empty()&&q.begin()->first<=i) q.erase(*q.begin());//去掉沒有覆蓋i+1的
    }
    cout<<(int)del.size()<<endl;
    for(int v:del) cout<<v<<' ';
    cout<<endl;
}

E

簡單dpdp,dpi,0dp_{i,0}dpi,1dp_{i,1}代表到第ii層最後使用電梯還是樓梯的最小值,直接轉移即可,時間複雜度O(n)O(n)

#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int N = 1e6+7;
ll dp[N][2];
ll a[N],b[N],ans[N];
int main(){
    int n,c;
    cin>>n>>c;
    for(int i=2;i<=n;i++) cin>>a[i];//st
    for(int i=2;i<=n;i++) cin>>b[i];//el
    memset(dp,0x3f,sizeof(dp));
    dp[1][0]=0;
    dp[1][1]=c;
    cout<<0;
    for(int i=2;i<=n;i++){
        dp[i][0]=min(dp[i-1][0]+a[i],dp[i-1][1]+a[i]);//st
        dp[i][1]=min(dp[i-1][0]+b[i]+c,dp[i-1][1]+b[i]);//el
        ans[i]=min(dp[i][0],dp[i][1]);
    }
    for(int i=2;i<=n;i++) cout<<' '<<ans[i];
    cout<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章