Codeforces Round #410 (Div. 2)

传送门

题意

A.询问改变一个字符是否能使字符串变成回文串
B.将字符串首字符放到尾部称为一次操作
给出n个字符串,询问使n个字符串变成相同字符串的 最少操作次数
C.给出A序列,\(a_i,a_{i+1}->a_i-a_{i+1},a_i+a_{i+1}\)称为一次操作
询问使得序列gcd>1的最少操作次数,不能输出-1
D.给出序列a,b,选出最多n/2+1个数,满足选出的数的2倍大于等于原序列数之和

分析

A.\(O(n/2)\)扫一遍统计不同字符数,注意a,abcba都满足A题意
B.直接$O(len^3n)暴力,注意细节
C.我们发现对于x,y
x,y都为奇,一次操作后x,y为偶
x,y其中一个为奇,两次操作后x,y为偶
那么我们先扫一遍判断是否有gcd>1,没有扫一遍处理相邻数都为奇的,再扫一遍处理相邻数为一奇一偶,证明见此
D.构造方法如下:
1.将A数组排序
2.记录第一个坐标,再每次看b[a[2
i].loc],b[a[2i+1].loc],如果b[a[2i].loc]>b[a[2i+1].loc],p[i+1]=a[2i].loc;否则p[i+1]=a[2i+1].loc
3.如果n为偶,再把最后一个添加进去
我们只证奇个数情况,b数组肯定满足性质,我们看a数组
除去第一个,我们选了n/2个数,可能选择的数都比未选的数都小,不妨记dex=a[2
i]-a[2*i+1],因为数都是正的,故n/2个dex之和必定小于a[1],请读者好好想一想,所以我们能保证a数组满足性质

trick

代码

只给出C和D的代码
C

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
#pragma comment(linker, "/STACK:102400000,102400000")

int n;
ll a[100100],ret,cnt;
inline ll gcd(ll x,ll y) { return y==0?x:gcd(y,x%y); }
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%lld",a+i);
    ret=gcd(abs(a[1]),abs(a[2]));
    for(int i=3;i<=n;++i) ret=gcd(ret,abs(a[i]));
    if(ret>1) { puts("YES");puts("0");return 0; }
    for(int i=1;i<n;++i)
    {
        ll x=abs(a[i]),y=abs(a[i+1]);
        if((x&1)&&(y&1)) {cnt++;a[i]=a[i+1]=2;}
    }
    for(int i=1;i<n;++i)
    {
        ll x=abs(a[i]),y=abs(a[i+1]);
        if(((x&1)&&(y%2==0))||((x%2==0)&&(y&1))) { cnt+=2;a[i]=a[i+1]=2; }
    }
    puts("YES");printf("%lld\n",cnt);
    return 0;
}

D

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n,b[100100];
struct node
{
    int loc,value;
    bool operator<(const node &p)const
    {
        return value>p.value;
    }
}a[100100];
int p[100100];
int cnt=0;
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;++i) {scanf("%d",&a[i].value);a[i].loc=i;}
    sort(a,a+n);
    for(int i=0;i<n;++i) scanf("%d",b+i);
    if(n%2==0)
    {
        p[cnt++]=a[0].loc;
        for(int i=1;i<n-1;i+=2)
        if(b[a[i].loc]>b[a[i+1].loc]) p[cnt++]=a[i].loc;else p[cnt++]=a[i+1].loc;
        p[cnt++]=a[n-1].loc;
    }
    else
    {
        p[cnt++]=a[0].loc;
        for(int i=1;i<n;i+=2)
        if(b[a[i].loc]>b[a[i+1].loc]) p[cnt++]=a[i].loc;else p[cnt++]=a[i+1].loc;
        //printf("p[i]=%d\n",p[cnt-1]);
    }
    //for(int i=0;i<n;++i) printf("a[%d].loc=%d\n",i,a[i].loc);
    printf("%d\n",cnt);
    for(int i=0;i<cnt;++i) printf("%d%c",p[i]+1,i==(cnt-1)?'\n':' ');
}
posted @ 2017-04-22 09:54  遗风忘语  阅读(108)  评论(0编辑  收藏  举报