【CF】Codeforces Round #530 (Div. 2)

好菜呀,本来感觉可以涨分的,,没想到C题水题有个地方G掉了fst了orz

A题

水题模拟
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>

using namespace std;

int w,h;
int u1,d1,u2,d2;
int main() {
    scanf("%d%d",&w,&h);
    scanf("%d%d%d%d",&u1,&d1,&u2,&d2);
    for(int i=h;i>=1;i--) {
        w += i;
        if(d1==i) w -= u1;
        if(d2==i) w -= u2;
        if(w<0) w = 0;
    }
    printf("%d",w);
}

B题

水题模拟
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main() {
    int n;
    cin>>n;
    int r = sqrt(n);
    int o = (n+r-1)/r;
    cout<<r+o<<endl;
}

C

水题模拟,然而本来应该for i in range[1,tot]的,然而我直接写了t+1就挂掉了orz
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 305;
int k,n;
char ss[maxn];
char t[maxn];
int tot;
void tuichu() {
    puts("Impossible");
    exit(0);
}

int main() {
    scanf("%s%d",&ss[1],&k);
    n = strlen(ss+1);
    int xin = 0; int liu = 0;
    int cnt = 0;
    for(int i=1;i<=n;i++) {
        if(ss[i]!='?'&&ss[i]!='*') cnt++;
        else {
            if(ss[i]=='?') liu++;
            else xin++;
        }
    }
    if( (cnt-xin-liu)>k||(cnt<k&&(!xin)) )  tuichu();
    if(xin) {
        int cl = cnt - xin - liu;
        int cp = k - cl;
        bool nw = 0;
        for(int i=1;i<=n;i++) {
            if(ss[i]=='*') {
                if(!nw) {
                    for(int j=1;j<=cp;j++) t[++tot] = ss[i-1];
                    nw = 1;
                }
                --tot;
            }
            else if(ss[i]=='?') {
                --tot;
            } else t[++tot] = ss[i];
        }
    } else {
        int cl = cnt - liu;
        int cp = k - cl;
        for(int i=1;i<=n;i++) {
            if(ss[i]=='?') {
                if(cp) --cp;
                else --tot;
            }
            else t[++tot] = ss[i];
        }
    }
    for(int i=1;i<=tot;i++) {
        putchar(t[i]);
    }
}

D

有一颗有根树n1e5,每个点都记了从根到那个点路径的权值和,但是深度为偶数的店的权值和为-1(自己去填),点权值都是未知,填树上的点权值,使得成立并且可以权值总和最小,不可以的输出-1 dfs一次,记录路径上的权值最大值,如果是奇数深度点,ANS+=S[x]-MX (S[x]为根到当前点权值和),偶数的话尽可能在满足题意的情况下选最大的填。如果往上的最大值大于当前S,无解。
#include<iostream>
#include<algorithm>
#include<cstdio>
#define int long long 
using namespace std;
const int maxn = 2e5+5;
int en[maxn],nt[maxn],la[maxn],owo;
void adg(int x,int y) {
    en[++owo]=y; nt[owo]=la[x]; la[x]=owo;
}
int n;
int ANS;
bool flag;
int S[maxn];
void dfs(int x,int dp,int mx) {
    if(dp==1) {
        if(mx>S[x]) { flag = 1; return; }
        ANS += S[x] - mx;
        for(int it=la[x];it;it=nt[it]) {
            int y = en[it];
            dfs(y,dp^1,max(mx,S[x]));
        }
    } else {
        if(!la[x]) return;
        int mi = 0x3f3f3f3f;
        for(int it=la[x];it;it=nt[it]) {
            mi = min(S[en[it]],mi);
        }
        if(mi<mx) { flag = 1; return; }
        ANS += mi - mx;
        for(int it=la[x];it;it=nt[it]) {
            int y = en[it];
            dfs(y,dp^1,mi);
        }
    }
}
main() {
    scanf("%I64d",&n);
    for(int i=2;i<=n;i++) {
        int x; scanf("%I64d",&x);
        adg(x,i);
    }
    for(int i=1;i<=n;i++) {
        scanf("%I64d",&S[i]);
    }
    dfs(1,1,0);
    if(!flag) printf("%I64d",ANS);
    else puts("-1");
}

E

真的看不懂题意orz orz orz 咕咕咕了

F

题意:给你一棵树,每个节点上有若干饼干,并且给出每个节点上吃一块饼干需要多少时间,同时给出走过一条边所需时间。 总时限为 T,两个人轮流进行操作: Mitya从当前节点选择一个子节点向下走,或者直接结束游戏并往根回动吃饼干; Vasya割断当前节点到其某个子节点的边,或者什么都不做。 问Mitya可以吃到的最多的多少块饼干。 题解:可以想到类似博弈里面,mitya的当前节点下面有若干个子树,那么vasya一定会切除掉最终会使得答案最大的那一个子树.同时对于原题中树上往回走操作考虑起来很迷,我们不如看做往下走的时候边花的时间*2就可以了.这样对于一个点就有两种选法,一个走到他次大的子树中去,一个在这个地方结束(看做把一路上的饼干收集起来,现在开始吃,回溯又把当前节点饼干放回去)计算吃饼干. 在计算某一个时间吃最多的饼干的时候,利用线段树维护.
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cmath>
#define int long long
using namespace std;
const int maxn = 2e6+5;
const int inf = 1e6;
int n,T;
int len[maxn],nt[maxn],en[maxn],la[maxn],owo;
void adg(int x,int y,int z) {
    en[++owo]=y; nt[owo]=la[x]; la[x]=owo; len[owo] = z;
}
int NUM[maxn],TM[maxn];
struct node{
    node *ls,*rs; int sumnum,sumtim;
}z[maxn],*rt;int ztot;
void upd(node *&p) {
    p->sumnum = p->ls->sumnum + p->rs->sumnum;
    p->sumtim = p->ls->sumtim + p->rs->sumtim;
    return;
}
void maketree(node *&p,int l,int r) {
    p = &z[++ztot];
    if(l==r) return;
    int mid = (l+r)>>1;
    maketree(p->ls,l,mid); maketree(p->rs,mid+1,r);
}
void addseg(node *&p,int l,int r,int x,int tt) {
    if(l==r) {
        p->sumnum += tt; p->sumtim += x*tt;
        return;
    }
    int mid = (l+r)>>1;
    if(x<=mid) addseg(p->ls,l,mid,x,tt);
    else addseg(p->rs,mid+1,r,x,tt);
    upd(p);
}
int query(node *&p,int l,int r,int tt) {
    if(p->sumtim<=tt) return p->sumnum;
    if(l==r) return min(tt/l,p->sumnum);
    int mid = (l+r)>>1;
    if(p->ls->sumtim>=tt) return query(p->ls,l,mid,tt);
    else return p->ls->sumnum + query(p->rs,mid+1,r,tt-p->ls->sumtim);
}
int dfs(int x,int t) {
    int mx1 = 0; int mx2 = 0;
    addseg(rt,1,inf,TM[x],NUM[x]);
    int orz = query(rt,1,inf,t);
    for(int it=la[x];it;it=nt[it]) {
        int y = en[it];
        if(len[it]*2>=t) continue;
        int oo = dfs(y,t-2*len[it]);
        if(oo>mx1) mx2 = mx1 , mx1 = oo;
        else if(oo>mx2) mx2 = oo;
    }
    addseg(rt,1,inf,TM[x],-NUM[x]);
    if(x==1) return max(orz,mx1);
    else return max(orz,mx2);
}
main() {
    scanf("%I64d%I64d",&n,&T);
    for(int i=1;i<=n;i++) {
        scanf("%I64d",&NUM[i]);
    }
    for(int i=1;i<=n;i++) {
        int tm;
        scanf("%I64d",&TM[i]);
    }
    for(int i=2;i<=n;i++) {
        int y,le;
        scanf("%I64d %I64d",&y,&le);
        adg(y,i,le);
    }
//  cerr<<"233"<<endl;
    maketree(rt,1,inf);
    printf("%I64d",dfs(1,T));
}
posted @ 2019-01-06 01:32  Newuser233  阅读(5)  评论(0)    收藏  举报