Codeforces Round #507 (Div. 2, based on Olympiad of Metropolises) A, B, D, E

Codeforces Round #507 (Div. 2, based on Olympiad of Metropolises) A, B, D, E


1040A. Palindrome Dance

题目链接
题意:

给一个串,由0,1,2组成,2可以用代价a变成0,用代价b变成1,问使其变成由0,1组成的回文串的最小花费

思路:

水题。贪心。

AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>


using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=ed;i>=st;--i)
#define TCASE(T)    cin>>T;while(T--)


const int MAXN = 100010;
const int MOD = 1e9+7;
const int INF = 1e9+7;

int _;

using namespace std;

int num[205];

int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w+",stdout);
    FSIO;
    int N;
    int a, b;
    while(cin>>N>>a>>b)
    {
        for(int i=1;i<=N;++i)   cin>>num[i];
        int ans = 0;
        int flag = 1;
        for(int i=1,j=N;i<j;++i,--j)
        {
            if(num[i]==2&&num[j]==2)    ans += 2*min(a,b);
            else if(num[i]==2&&num[j]!=2)
            {
                if(num[j]==0)   ans += a;
                else    ans += b;
            }
            else if(num[j]==2&&num[i]!=2)
            {
                if(num[i]==0)   ans += a;
                else    ans += b;
            }
            else if(num[i]!=2&&num[j]!=2&&num[i]!=num[j])
            {
                flag = 0;
                break;
            }
        }
        if(N%2==1&&num[N/2+1]==2)   ans += min(a,b);
        if(flag)    cout<<ans<<endl;
            else    cout<<-1<<endl;
    }
    return 0;
}

1040B. Shashlik Cooking

题目链接
题意:

对一个长为n的串进行反转操作,每次选择p,则反转离p距离小于等于k的所有位置,问使得所有位置都被反转的最小操作次数。

思路:

水题。分类讨论,具体见代码。

AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>


using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=ed;i>=st;--i)
#define TCASE(T)    cin>>T;while(T--)


const int MAXN = 100010;
const int MOD = 1e9+7;
const int INF = 1e9+7;

int _;

using namespace std;


int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w+",stdout);
    FSIO;
    int N, K;
    while(cin>>N>>K)
    {
        int st = -1;
        int ed = -1;
        if(N%(2*K+1)==0)    st=K+1, ed=N-K;
        else if(N%(2*K+1)>K)    st=K+1, ed=N-((N%(2*K+1))-K)+1;
        else if(N%(2*K+1)<=K)    st=1, ed=N-(N%(2*K+1))+1;
        int ans = (N+2*K+1-N%(2*K+1))/(2*K+1);
        if(N%(2*K+1)==0)    ans = (N/(2*K+1));
        cout<<ans<<endl;
        for(int i=st;i<ed;i+=(2*K+1))
            cout<<i<<" ";
        cout<<ed<<endl;
    }
    return 0;
}

1040D. Subway Pursuit

题目链接
题意:

在[1,N]这N个位置上有一个点在运动,每个单位时间移动K步。每个时间你可以给出一个[l,r]询问,如果点在该区间内评测机返回YES,否则是NO。你最多可以询问4500次。

思路:

假设在询问某个区间时该点在该区间[l,r]内,那么下一次询问的整个区间范围将会是[l-K,r+K](当然应该是[1,N]的一个子区间。用二分法不断缩小询问区间,直至到一定范围内随机枚举即可,多次试验发现60是最快的(30ms)。

AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=ed;i>=st;--i)
#define TCASE(T)    cin>>T;while(T--)


const int MAXN = 500005;
const ll MOD = 1e9+7;
const int INF = 1e9+7;

int _;

using namespace std;

int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w+",stdout);
    FSIO;
    ll N, K;    cin>>N>>K;
    string tmp;
    srand(time(0));
    ll minn = 1, maxn = N;
    while (1)
    {
        if (maxn-minn+1 <= 50)
        {
            ll attempt = minn + rand()%(maxn-minn+1);
            cout << attempt << " " << attempt << endl;
            fflush(stdout);
            cin >> tmp;
            if (tmp[0] == 'N')
            {
                minn = max(1LL, minn-K);
                maxn = min(N, maxn+K);
            }
            else break;
        }
        else
        {
            ll mid = (minn+maxn)>>1;
            cout << minn << " " << mid << endl;
            fflush(stdout);
            cin >> tmp;
            if(tmp[0] == 'Y')
            {
                minn = max(1LL, minn-K);
                maxn = min(N, mid+K);
            }
            else
            {
                minn = max(1LL, mid-K);
                maxn = min(N, maxn+K);
            }
        }
    }
    return 0;
}

1040E. Network Safety

题目链接
题意:

给一个由N个顶点,M条边组成的有向图,每个点都有权值 ci c i ,给定K, ci c i 属于 [0,2k1] [ 0 , 2 k − 1 ] 。求这样的对数 (A,x) ( A , x ) ,A是原图的一个可以为空的点集子集,x属于 [0,2k1] [ 0 , 2 k − 1 ] ,使得A的每个点的权值变为 cix c i ⊕ x ,且每一条边连接的两个点的权值不同。

思路:

根据异或运算的性质: ab=c,cb=a 如 果 a ⊕ b = c , 那 么 c ⊕ b = a
所以对每一个相邻的点对 (i,j) ( i , j ) ,当x为 cicj c i ⊕ c j 时,他们要么被选入A,要么全不被选入A,此时,每个连通分支可以看作一个点。对当前x的选择方案即这样的连通分支的数量(设为t),对答案的贡献为 2t 2 t ,用并查集维护即可。

AC代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>


using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=ed;i>=st;--i)
#define TCASE(T)    cin>>T;while(T--)


const int MAXN = 100010;
const int MOD = 1e9+7;
const int INF = 1e9+7;

int _;

using namespace std;


int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w+",stdout);
    FSIO;
    int N, K;
    while(cin>>N>>K)
    {
        int st = -1;
        int ed = -1;
        if(N%(2*K+1)==0)    st=K+1, ed=N-K;
        else if(N%(2*K+1)>K)    st=K+1, ed=N-((N%(2*K+1))-K)+1;
        else if(N%(2*K+1)<=K)    st=1, ed=N-(N%(2*K+1))+1;
        int ans = (N+2*K+1-N%(2*K+1))/(2*K+1);
        if(N%(2*K+1)==0)    ans = (N/(2*K+1));
        cout<<ans<<endl;
        for(int i=st;i<ed;i+=(2*K+1))
            cout<<i<<" ";
        cout<<ed<<endl;
    }
    return 0;
}#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <stack>
#include <bitset>

using namespace std;

#define FSIO  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define DEBUG(a)   cout<<"DEBUG: "<<(a)<<endl;
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define X  first
#define Y  second
#define REP(i,st,ed)    for(int i=st;i<=ed;++i)
#define IREP(i,st,ed)   for(int i=ed;i>=st;--i)
#define TCASE(T)    cin>>T;while(T--)


const int MAXN = 500005;
const ll MOD = 1e9+7;
const int INF = 1e9+7;

int _;

using namespace std;

int curedgeno;
int tot;
vector<int> rec[MAXN];
map<ll,int> mapp;

struct Edge
{
    int u, v;
    int next;
    Edge(int u=0, int v=0, int next=-1): u(u), v(v), next(next) {}
} edge[MAXN];


void add_edge(int index, int u, int v)
{
    ++curedgeno;
    edge[curedgeno] = Edge(u,v);
    rec[index].pb(curedgeno);
}



ll num[MAXN];
ll po2[MAXN];

struct DSU
{
    int fa[MAXN], sz;
    int n;
    void init(int n)
    {
        this->n = n;
        memset(fa,-1,sizeof(fa));
        sz = n;
    }
    int find(int x)
    {
        return fa[x]==-1 ? x : fa[x]=find(fa[x]);
    }
    void merge(int x,int y)
    {
        x=find(x),y=find(y);
        if(x>y) swap(x,y);
        if(x!=y)
        {
            fa[x]=y;
            sz--;
        }
    }
    int count_p()
    {
        /*for(int i=1;i<=n;++i)   cout<<fa[i]<<" ";
        cout<<endl;*/
        return sz;
    }
} dsu;
int N, M, K;

void init()
{
    po2[0] = 1LL;
    ll lli = max(N,K);
    for(int i=1; i<=lli; ++i)
        po2[i]=po2[i-1]*2LL%MOD;
    tot=0;
    mapp.clear();
    for(int i=1; i<=M; ++i) rec[i].clear();
    curedgeno = 0;
}

inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    for(; !isdigit(ch); ch=getchar())if(ch=='-')f=-1;
    for(; isdigit(ch); ch=getchar())x=x*10+ch-'0';
    return x*f;
}

int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w+",stdout);
    ll u, v;
    N =read();
    M =read();
    K =read();

    init();
    for(int i=1; i<=N; ++i)   num[i]=read();
    for(int i=1; i<=M; ++i)
    {
        u=read();
        v=read();
        ll tmp = num[u]^num[v];
        if(mapp[tmp])   add_edge(mapp[tmp],u,v);
        else
        {
            mapp[tmp] = ++tot;
            add_edge(tot,u,v);
        }
    }
    ll ans = (po2[K]-mapp.size()+MOD)*po2[N]%MOD;
    dsu.init(N);
    for(int tt=1;tt<=tot;++tt)
    {
        dsu.sz = N;
        int sz = rec[tt].size();
        for(int i=0; i<sz; ++i)
        {
            Edge& e = edge[rec[tt][i]];
            dsu.merge(e.u,e.v);
        }
        //DEBUG(dsu.count_p());
        ans = (ans+po2[dsu.count_p()])%MOD;
        for(int i=0; i<sz; ++i)
        {
            Edge& e = edge[rec[tt][i]];
            dsu.fa[e.v] = -1;
            dsu.fa[e.u] = -1;
        }
    }
    cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值