NOIP2012题解

T1Vigenère 密码

传送门

题解:字符串模拟

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
char k[1010],s[1010],ans[1010];
int len1,len2;
int main()
{
    gets(k);
    gets(s);
    len1=strlen(k);
    len2=strlen(s);
    if(len1<len2)
        for(int i=len1;i<len2;i++)    k[i]=k[i-len1];
    for(int i=0,j;i<len2;i++)
    {
        if(k[i]>='A'&&k[i]<='Z')    j=k[i]-'A';
        if(k[i]>='a'&&k[i]<='z')    j=k[i]-'a';
        ans[i]=s[i]-j;
        if(s[i]>='A'&&s[i]<='Z')
            if(ans[i]<'A')    ans[i]+=26;
        if(s[i]>='a'&&s[i]<='z')
            if(ans[i]<'a')    ans[i]+=26;
    }
    for(int i=0;i<len2;i++)    printf("%c",ans[i]);
    return 0;
}
AC

T2国王游戏

传送门

题解:贪心,按左右手乘积排序

假设最后两个人为i,j.要求最后一个人得分小则满足(sum为i之前所有人左手乘积)

sum*left[j]/right[i]>sum*left[i]/right[j],式子两边为i,j在最后一个位置时,i/j的得分。

消去sum,left[j]*right[j]>left[i]*right[i],也就是最后一个人得分比前一个人少,必须left*right大。

从大臣队伍末尾一直推到前面就可以。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 1020
#define LL long long
using namespace std;

int n;
LL ret,cur;
struct King{
    int l,r,p;
}a[maxn];

bool cmp(King a,King b){
    return a.p<b.p;
}

void read(int &x){
    char ch=getchar();x=0;int f=1;
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    x=x*f;
}

int main(){
//    freopen("game.in","r",stdin);
//    freopen("game.out","w",stdout);
    read(n);
    read(a[0].l);read(a[0].r);
    for(int i=1;i<=n;i++){
        read(a[i].l);read(a[i].r);
        a[i].p=a[i].l*a[i].r;
    }
    sort(a+1,a+n+1,cmp);
    cur=a[0].l;
    for(int i=1;i<=n;i++){
        ret=max(ret,cur/a[i].r);
        cur=cur*a[i].l;
    }
    cout<<ret<<endl;
//    fclose(stdin);fclose(stdout);
    return 0;
}
非高精版本

T3开车旅行

传送门

题解:暴力20..为什么每次暴力都是20...

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define maxn 1000000
#define inf 2147483647
using namespace std;

int n,m,s,cur,h[maxn],dis[maxn][3],v[maxn][3];
LL ans,lena,lenb,x0;
int Dis(int x,int y){int p=h[x]-h[y];return p<0?-p:p;}
LL min_(LL a,LL b){return a<b?a:b;}

void Start(int st){
    int tmp=st,cnt=1;lena=0,lenb=0;
    for(;cnt;cnt++){
        if(cnt&1){
            if(lena+lenb+dis[st][1]>x0){
                LL k;
                if(lenb==0)k=inf;
                else k=lena/lenb;
                if(k<ans){
                    ans=k;cur=tmp;
                }else if(k==ans){
                    if(h[tmp]>h[cur])cur=tmp;
                }
                return;
            }
            lena+=dis[st][1];
            st=v[st][1];
        }else {
            if(lena+lenb+dis[st][0]>x0){
                LL k;
                if(lenb==0)k=inf;
                else k=lena/lenb;
                if(k<ans){
                    ans=k;cur=tmp;
                }else if(k==ans){
                    if(h[tmp]>h[cur])cur=tmp;
                }
                return;
            }
            lenb+=dis[st][0];
            st=v[st][0];
        }
    } 
}

int main(){
//    freopen("drive.in","r",stdin);
//    freopen("drive.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&h[i]);//输入高度 
    memset(dis,0x3f,sizeof(dis)); 
    for(int i=1;i<=n;i++){               //预处理最远和次远 
        for(int j=i+1;j<=n;j++){
            int k=Dis(i,j);
            if(k==dis[i][0]){
                if(h[j]<h[v[i][0]]){
                    v[i][1]=v[i][0];dis[i][1]=dis[i][0];
                    v[i][0]=j;
                }
            }else if(k<dis[i][0]){
                dis[i][1]=dis[i][0];v[i][1]=v[i][0];
                dis[i][0]=k;v[i][0]=j;
            }else if(k==dis[i][1]){
                if(h[j]<h[v[i][1]])v[i][1]=j;
            }else if(k<dis[i][1]){
                dis[i][1]=k;v[i][1]=j;
            }
        }
    }
    scanf("%d",&x0);ans=inf;
    for(int i=1;i<=n;i++)Start(i);
    printf("%d
",cur);
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d%lld",&s,&x0);ans=inf;
        Start(s);printf("%lld %lld
",lena,lenb);
    }
//    fclose(stdin);fclose(stdout);
    return 0;
} 
AC

T1同余方程

传送门

题解:扩展欧几里得

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;

LL a,b,x,y;

void exgcd(LL a,LL b,LL &x,LL &y){
    if(b==0){
       x=1;y=0;
       return;
    }
    exgcd(b,a%b,x,y);
    LL t=x;x=y;y=t-a/b*y;
}

int main(){
//    freopen("mod.in","r",stdin);
//    freopen("mod.out","w",stdout);
    scanf("%lld%lld",&a,&b);
    exgcd(a,b,x,y);
    printf("%lld
",(x+b)%b);
//    fclose(stdin);fclose(stdout);
    return 0;
}
AC

T2借教室

传送门

题解:线段树区间修改和区间最小值

线段树95..可能我线段树常数略大..

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000009
#define inf 1000000009
using namespace std;

int n,m,s,t,d,flag;
int w[maxn];
struct Tree{
    int l,r,mn,s;
}tr[maxn<<2];

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

void pushdown(int rt){
    if(!tr[rt].s)return;
    tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s;
    tr[rt<<1].mn-=tr[rt].s;tr[rt<<1|1].mn-=tr[rt].s;
    tr[rt].s=0;return;
}

void pushup(int rt){
    tr[rt].mn=min(tr[rt<<1].mn,tr[rt<<1|1].mn);
    return;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].mn=w[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void update(int rt,int l,int r,int ql,int qr,int p){
    if(l>=ql&&r<=qr){
        tr[rt].mn-=p;
        tr[rt].s+=p;
        return;
    }
    int mid=(l+r)>>1;
    if(ql<=mid)update(rt<<1,l,mid,ql,qr,p);
    if(qr>mid)update(rt<<1|1,mid+1,r,ql,qr,p);
    pushup(rt);
}

int query_mn(int rt,int l,int r,int ql,int qr){
    pushdown(rt);
    if(l>=ql&&r<=qr){
        return tr[rt].mn;
    }
    int ans=inf,mid=(l+r)>>1;
    if(ql<=mid)ans=min(ans,query_mn(rt<<1,l,mid,ql,qr));
    if(qr>mid)ans=min(ans,query_mn(rt<<1|1,mid+1,r,ql,qr));
    return ans;
}

int main(){
//    freopen("classroom.in","r",stdin);
////    freopen("classroom.out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;i++)read(w[i]);
    build(1,1,n);
    for(register int i=1;i<=m;i++){
        read(d);read(s);read(t);
        if(k>=d)update(1,1,n,s,t,d);
        else {
            printf("-1
");
            printf("%d
",i);
            return 0;
        }
    }
        puts("0");
//    fclose(stdin);fclose(stdout);
    return 0;
}
AC

T3疫情控制

传送门

原文地址:https://www.cnblogs.com/zzyh/p/7698970.html