Codeforces Round #469 (Div. 2)

A题  水题 不解释

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
int l,r,a;
int main(){
    scanf("%d%d%d",&l,&r,&a);
    if(l>r)swap(l,r);
    if(l+a<r)printf("%d\n",(l+a)*2);
    else{
        a=a-(r-l),l=r;
        printf("%d\n",l*2+a/2*2);
    }
}

B题  从左到右贪心  能选就选

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=100050;
int n,m,tempa,tempb,ans,nb=1,a[N],b[N];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)scanf("%d",&b[i]);
    for(int i=1;i<=n;i++){
        tempa+=a[i];
        while(tempb<tempa)tempb+=b[nb],nb++;
        if(tempa==tempb)tempa=tempb=0,ans++;
    }
    printf("%d\n",ans);
}

C题     

定义以0开始和结尾  中间01相间的串是"zebra"串

给你一个串    问它能不能分成k个子序列  使得这k个子序列都是"zebra"串

Special Judge

 

开两个set  分别存 0 1  出现的位置

贪心选取即可

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=200500;
char s[N];
set<int>a,b;
vector<int>vec[N];
set<int>::iterator ita,itb;
int top,n;
int main(){
    scanf("%s",s+1),n=strlen(s+1);
    for(int i=1;i<=n;i++){
        if(s[i]=='0')a.insert(i);
        else b.insert(i);
    }
    while(!b.empty()){
        if(a.empty()){puts("-1");return 0;}
        ita=a.begin();
        vec[++top].push_back(*ita);
        while(1){
//            printf("*ita=%d\n",*ita);
            itb=b.lower_bound(*ita);
//            printf("itb=%d\n",*itb);
            if(itb==b.end()){a.erase(ita);break;}
//            printf("!");
            a.erase(ita);
            vec[top].push_back(*itb);
            ita=a.lower_bound(*itb);
            if(ita==a.end()){puts("-1");return 0;}
            vec[top].push_back(*ita);
            b.erase(itb);
        }
    }
    while(!a.empty()){
        vec[++top].push_back(*(ita=a.begin()));
//        printf("%d\n",*ita);
        a.erase(ita);
    }
    printf("%d\n",top);
    for(int i=1;i<=top;i++){
        printf("%d ",vec[i].size());
        for(int j=0;j<vec[i].size();j++){
            printf("%d ",vec[i][j]);
        }puts("");
    }
}

D题   

找规律

n是奇数 -> 前n/2+1的数的位置不变   剩下的递归n/2并插空  循环右移一个位置

n是偶数 ->前n/2的数的位置不变   递归n/2

 

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
#define int long long
int solve(int x,int y){
    if((y&1)&&x<=y&&(x&1))return x/2+1;
    else if(((y&1)==0)&&x<y&&(x&1))return x/2+1;
    else if((y&1)==1){
        if(x==2)return solve(y/2,y/2)+y/2+1;
        else return solve(x/2-1,y/2)+y/2+1;
    }
    elsereturn solve(x/2,y/2)+y/2;
}
int n,q,x;
signed main(){
    scanf("%I64d%I64d",&n,&q);
    while(q--){
        scanf("%I64d",&x);
        printf("%I64d\n",solve(x,n));
    }
}

E 连边tarjan 找入度为0的且点数最小的强连通分量

连边的要求  x=(y+1)%h  x->y连边

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
const int N=200050;
int n,m,h,u[N],xx,yy,v[N],nxt[N],first[N],tot,ans=0x3f3f3f3f;
int low[N],dfn[N],cnt,vis[N],s[N],p[N],top,t,V[N],tempans,out[N];
void add(int x,int y){v[tot]=y,nxt[tot]=first[x],first[x]=tot++;}
void tarjan(int x){
    low[x]=dfn[x]=++cnt;vis[x]=1;s[++top]=x;
    for(int i=first[x];~i;i=nxt[i])
        if(!dfn[v[i]])tarjan(v[i]),low[x]=min(low[x],low[v[i]]);
        else if(vis[v[i]])low[x]=min(low[x],dfn[v[i]]);
    if(low[x]==dfn[x]){t++;do xx=s[top--],vis[xx]=0,p[xx]=t,V[t]++;while(xx!=x);}
}
int main(){
    memset(first,-1,sizeof(first));
    scanf("%d%d%d",&n,&m,&h);
    for(int i=1;i<=n;i++)scanf("%d",&u[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&xx,&yy);
        if(u[xx]==(u[yy]+1)%h)add(yy,xx);
        if(u[yy]==(u[xx]+1)%h)add(xx,yy);
    }
    for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
    for(int i=1;i<=n;i++)
        for(int j=first[i];~j;j=nxt[j])
            if(p[i]!=p[v[j]])out[p[i]]=1;
    for(int i=1;i<=n;i++){
        if(!out[p[i]]&&ans>V[p[i]])tempans=p[i],ans=V[p[i]];
    }printf("%d\n",ans);
    for(int i=1;i<=n;i++)if(p[i]==tempans)printf("%d ",i);
}

贪心

//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,d,b,a[100050],cntl,cntr;
int sum(int l,int r){
    if(l<1)l=1;if(r>n)r=n;
    return a[r]-a[l-1];
}
signed main(){
    scanf("%I64d%I64d%I64d",&n,&d,&b);
    for(int i=1;i<=n;i++)scanf("%I64d",&a[i]),a[i]+=a[i-1];
    for(int i=1;i<=n/2;i++){
        if(sum(1,i*(d+1))>=(cntl+1)*b)cntl++;
        if(sum(n-i+1-i*d,n)>=(cntr+1)*b)cntr++;
    }printf("%I64d\n",max(n/2-cntl,n/2-cntr));
}

 

posted @ 2018-03-10 18:34  SiriusRen  阅读(188)  评论(0编辑  收藏  举报