Codeforces357

A.Group of Students

代码:

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

const int MAXM=100+2;
int M,a[MAXM],x,y;

int main(){
    cin >> M;
    for(int i=1;i<=M;i++) scanf("%d",a+i),a[i]+=a[i-1];
    cin >> x >> y;

    for(int i=2,s,t;i<=M;i++){
        s=a[i-1],t=a[M]-a[i-1];
        if(x<=s && s<=y && x<=t && t<=y){
            cout << i << endl;
            return 0;
        }
    }
    cout << 0 << endl;

    return 0;
}
View Code

 

B.Flag Day

代码:

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

const int MAXN=100000+2;
int N,M,r[MAXN];

int main(){
    cin >> N >> M;
    for(int i=1,a,b,c;i<=M;i++){
        cin >> a >> b >> c;

        if(!r[a] && !r[b] && !r[c]) r[a]=1,r[b]=2,r[c]=3;
        else if(r[a]==1) r[b]=2,r[c]=3;
        else if(r[b]==1) r[a]=2,r[c]=3;
        else if(r[c]==1) r[a]=2,r[b]=3;
        else if(r[a]==2) r[b]=1,r[c]=3;
        else if(r[b]==2) r[a]=1,r[c]=3;
        else if(r[c]==2) r[a]=1,r[b]=3;
        else if(r[a]==3) r[b]=1,r[c]=2;
        else if(r[b]==3) r[a]=1,r[c]=2;
        else if(r[c]==3) r[a]=1,r[b]=2;
    }
    for(int i=1;i<=N;i++) cout << r[i] << " ";
    cout << endl;

    return 0;
}
View Code

 

C.Knight Tournament

题意:N个人参加M场比赛,每场比赛为[li,ri]之间,且未被淘汰的人比拼,每场比赛只有一个胜者,已知每场比赛的胜者xi,求某个人是被谁打败的。

题解:模拟很显然,问题在于如何优化更新的过程,由于是区间修改,单点修改,所以可以想到用线段树来维护。由于先进行的比赛优先级更高,所以我们从后向前更新,每次更新[li,xi-1],[xi+1,ri](因为xi还未被打败)。

代码:

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

const int MAXN=300000+2;
const int MAXM=300000+2;
struct NODE{
    int l,r,v;
}t[6*MAXN];
int N,M,l[MAXM],r[MAXM],x[MAXM];

void Pushdown(int x){
    if(!t[x].v) return;
    t[2*x].v=t[2*x+1].v=t[x].v;
    t[x].v=0;
}

void Build(int x,int l,int r){
    t[x].l=l,t[x].r=r,t[x].v=0;
    if(l==r) return;

    int m=(l+r)>>1;
    Build(2*x,l,m),Build(2*x+1,m+1,r);
}

void Update(int x,int l,int r,int v){
    if(r<l) return;
    if(l<=t[x].l && t[x].r<=r){
        t[x].v=v;
        return;
    }
    Pushdown(x);

    int m=(t[x].l+t[x].r)>>1;
    if(l<=m) Update(2*x,l,r,v);
    if(r>m) Update(2*x+1,l,r,v);
}

int Query(int x,int p){
    if(t[x].l==t[x].r) return t[x].v;
    Pushdown(x);

    int m=(t[x].l+t[x].r)>>1;
    if(p<=m) return Query(2*x,p);
    else return Query(2*x+1,p);
}

int main(){
    cin >> N >> M;

    Build(1,1,N);
    for(int i=1;i<=M;i++) scanf("%d %d %d",l+i,r+i,x+i);
    for(int i=M;i;i--){
        Update(1,l[i],x[i]-1,x[i]);
        Update(1,x[i]+1,r[i],x[i]);
    }
    for(int i=1,x;i<=N;i++){
        x=Query(1,i);
        if(x==i) cout << 0 << " ";
        else cout << x << " ";
    }

    return 0;
}
View Code

 

D.Xenia and Hamming

题意:给定两个长度相同的字符串A B,两者分别由循环节x y构成,求A B的字符不同的位置的个数。

题解:最先想到的是用lcm(L(x),L(y)),暴力算出一个的,但是显然会T。显然统计相同的位数会更简单一些,考虑性质:假如A[i]和B[j]有概率匹配,当且仅当i≡j(mod gcd(L(x),L(y))),所以对于每一位,我们只需要考虑其mod gcd后的位置即可。因此我们改变枚举的方式,改为枚举余数。

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long

const int MAXL=1000000+2;
const int MAXK=26+2;
ll N,M,C,LS,LT,G,L,RS[MAXL][MAXK];
char S[MAXL],T[MAXL];

ll gcd(ll a,ll b){
    if(a<b) swap(a,b);
    return (b?gcd(b,a%b):a);
}

int main(){
    cin >> N >> M;
    scanf("%s %s",S,T);
    LS=strlen(S),LT=strlen(T);
    G=gcd(LS,LT),L=LS*LT/G;

    for(int i=0;S[i];i++) RS[i%G][S[i]-'a']++;
    for(int i=0;T[i];i++) C+=RS[i%G][T[i]-'a'];
    cout << N*LS-N*LS/L*C;

    return 0;
}
View Code

 

E.Compartments

(待补)

posted @ 2019-03-12 20:36  WDZRMPCBIT  阅读(146)  评论(0编辑  收藏  举报