Codeforces Round #582 (Div. 3) D2,E,F,G

D2 Equalizing by Division (hard version)

將每個數從除2除2移動中,保存能到達的地方的步數。然後暴力枚舉i,i數能否有k個數相同。水題一個,但是我思路不是這個,是另一種優先隊列的做法,無奈一直wa8.

每個數提供的數最多是log(1e5)個,所有的之和是n*log(1e5),每個數遍歷一次,所以不會超時

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],vis[N];
multiset<int> st[N];
void cal(int x)
{
    int cnt=0;
    while(x)
    {
        st[x].insert(cnt++);
        x/=2;
    }
    st[0].insert(cnt);
}
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;++i)
    {
        int x;
        cin>>x;
        cal(x);
    }
    int ans=0x3f3f3f3f;
    for(int i=200000;i>=0;--i)
    {
        if(st[i].size()>=k)
        {
            int tmp=0;
            int num=1;
            for(auto it=st[i].begin();it!=st[i].end()&&num<=k;it++)
            {
                num++;
                tmp+=*it;
            }
            ans=min(ans,tmp);
        }
    }
    printf("%d\n",ans);
}

Two Small Strings

題意:給定一個整數n和兩個長度爲2的字符,只包含a,b,c。構造一個字符串包含n個a,n個b,n個c。

極其複雜的構造,具體詳情看代碼吧

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
char a[3],b[3];
int main()
{
    int n;
    cin>>n;
    cin>>a>>b;
    puts("YES");
    int t='a'+'b'+'c';
    if(a[0]==a[1]&&b[0]==b[1]&&a[0]==b[0])
    {
        if(a[0]=='A') rep(i,1,n) {
            printf("b");
            printf("a");
            printf("c");
        }
        else if(a[0]=='B')rep(i,1,n) {
            printf("c");
            printf("b");
            printf("a");
        }
        else rep(i,1,n) {
            printf("b");
            printf("c");
            printf("a");
        }
        return 0;
    }
    if(a[0]==a[1]&&b[0]==b[1])
    {
        rep(i,1,n)
        {
            printf("%c",a[0]);
            printf("%c",t-a[0]-b[0]);
            printf("%c",b[0]);
        }
        return 0;
    }
    if(a[0]==b[1]&&a[1]==b[0])
    {
        //printf("***\n");
        rep(i,1,n) printf("%c",a[1]);
        rep(i,1,n) printf("%c",t-a[1]-a[0]);
        rep(i,1,n) printf("%c",a[0]);
        return 0;
    }
    if(a[0]==a[1])
    {
        rep(i,1,n){
            printf("%c",b[1]);
            printf("%c",b[0]);
            printf("%c",t-b[1]-b[0]);
        }
        return 0;
    }
    if(b[0]==b[1])
    {
        rep(i,1,n) {
            printf("%c",a[1]);
            printf("%c",a[0]);
            printf("%c",t-a[1]-a[0]);
        }
        return 0;
    }


    if(a[0]==b[0])
    {
        rep(i,1,n) printf("%c",b[1]);
        rep(i,1,n) printf("%c",t-b[1]-b[0]);
        rep(i,1,n) printf("%c",b[0]);
        return 0;
    }
    if(a[0]==b[1])
    {
        rep(i,1,n) printf("%c",a[1]);
        rep(i,1,n) printf("%c",a[0]);
        rep(i,1,n) printf("%c",b[0]);
        return 0;
    }
    if(a[1]==b[0])
    {
        rep(i,1,n) printf("%c",b[1]);
        rep(i,1,n) printf("%c",b[0]);
        rep(i,1,n) printf("%c",a[0]);
        return 0;
    }
    if(a[1]==b[1])
    {
        rep(i,1,n) printf("%c",b[1]);
        rep(i,1,n) printf("%c",a[0]);
        rep(i,1,n) printf("%c",b[0]);
        return 0;
    }
}

 

F. Unstable String Sort

題解學習來自:https://blog.csdn.net/liufengwei1/article/details/100168302

很秀的做法。我的tarjan還是不能脫板,要看板子,然後有個地方沒有打好,一直在wa,也沒有懷疑板子問題。

唉,還是要儘量理解。

具體做法:tarjan縮點+拓撲排序

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=2e5+10;
vector<int>G[N],g[N];
int dfn[N],low[N],in[N],scc[N],a[N],b[N],ans[N];
int fa[N];
int n,k,index,sccnum;
stack<int>que;
int id;

void tarjan(int root)
{
    dfn[root]=low[root]=++index;
    que.push(root);
    for(int v:G[root])
    {
        if(!dfn[v])
        {
            tarjan(v);
            low[root]=min(low[root],low[v]);
        }
        else if(!scc[v]) low[root]=min(low[root],dfn[v]);
    }
    if(low[root]==dfn[root])
    {
        sccnum++;
        int x;
        do{
            x=que.top();que.pop();
            scc[x]=sccnum;
        }while(x!=root);
    }
}
void topo()
{
    queue<int>que;
    for(int i=1;i<=sccnum;++i) if(in[i]==0) que.push(i);
    id=0;
    while(que.size())
    {
        int x=que.front();que.pop();
        if(id<26)id++;
        b[x]=id-1;
        for(int v:g[x])
        {
            in[v]--;
            if(in[v]==0) que.push(v);
        }
    }
}

int main()
{
    cin>>n>>k;
    rep(i,1,n) cin>>a[i];
    for(int i=1;i<n;++i) G[a[i]].push_back(a[i+1]);
    rep(i,1,n) cin>>a[i];
    for(int i=1;i<n;++i) G[a[i]].push_back(a[i+1]);
    
    for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;++i)
    {
        for(int v:G[i])
        {
            //if(scc[i]!=scc[v]&&fa[scc[v]]!=scc[i])
            if(scc[i]!=scc[v])
            {
                fa[scc[v]]=scc[i];
                g[scc[i]].pb(scc[v]);
                in[scc[v]]++;
            }
        }
    }
    topo();
    if(id<k)
    {
        puts("NO");
        return 0;
    }
    for(int i=1;i<=n;++i) ans[i]=b[scc[i]];
    puts("YES");
    for(int i=1;i<=n;++i) printf("%c",ans[i]+'a');
}
/*
3 1
1 3 2
3 2 1
*/

Path Queries

並查集維護答案。

題意:給一個樹,每條邊有邊權,m次詢問。

每次詢問給定一個x,問樹上路徑(u,v)最大值的數小於等於x。

這題初步看好像很難,其實就是有點難。

做法:從小枚舉邊權,計算當前邊權w的答案,答案就這條邊兩端的連通塊相乘,siz[u]*siz[v]。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,m;
vector<int>g1[N],g2[N];
int siz[N];
int fa[N];
int find(int x)
{
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}
ll ans[N];
ll meger(int x1,int y1)
{
    int x=find(x1);
    int y=find(y1);
    ll res=0;
    if(x!=y)
    {
        fa[x]=y;
        res=1ll*siz[x]*siz[y];
        siz[y]+=siz[x];
    }
    return res;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<n;++i)
    {
        int u,v,w;
        cin>>u>>v>>w;
        g1[w].pb(u);
        g2[w].pb(v);
    }
    for(int i=1;i<=n;++i) siz[i]=1,fa[i]=i;
    for(int i=1;i<=200000;++i)
    {
        ans[i]=ans[i-1];
        for(int j=0;j<g1[i].size();++j)
        ans[i]+=meger(g1[i][j],g2[i][j]);
    }
    while(m--)
    {
        int q;
        cin>>q;
        printf("%lld ",ans[q]);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章