Codeforces1099

A.Snowball

代码:

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

int w,h,u1,d1,u2,d2;

int main(){
    cin >> w >> h >> u1 >> d1 >> u2 >> d2;
    while(h){
        w+=h;
        if(h==d1) w-=u1;
        if(h==d2) w-=u2;
        if(w<0) w=0;
        h--;
    }
    cout << w << endl;

    return 0;
}
View Code

 

B.Squares and Segments

代码:(这题题意貌似有点问题,应该是要求满足面积大于等于N的最小花费)

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

int N,a,b;

int main(){
    cin >> N;

    a=b=1;
    for(int i=1;i<=N;i++){
        if(a*b>=N) break;
        if(a<b) a++;
        else b++;
    }
    cout << a+b << endl;

    return 0;
}
View Code

 

C.Postcard

代码:

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

const int MAXN=200+2;
int N,c1,c2,K,p;
char S[MAXN];
string T;

int main(){
    cin >> S >> K;
    for(int i=0;S[i];i++)
        if(S[i]>='a' && S[i]<='z') N++;
        else if(S[i]=='?') c1++;
        else c2++,p=i;

    if(N<=K){
        if(!c2 && N!=K) cout << "Impossible";
        else{
            for(int i=0;S[i];i++){
                if(S[i]>='a' && S[i]<='z') cout << S[i];
                else if(S[i]=='?') continue;
                else if(i==p)
                    for(int j=1;j<=K-N;j++) cout << S[i-1];
            }
        }
    }
    else{
        if(N-K>c1+c2) cout << "Impossible";
        else{
            for(int i=strlen(S)-1;i>=0;i--){
                if(S[i]>='a' && S[i]<='z') T.push_back(S[i]);
                else if(N>K) i--,N--;
            }
            reverse(T.begin(),T.end());
            cout << T;
        }
    }
    cout << endl;

    return 0;
}
View Code

 

D.Sum in the tree

题意:给定一颗树中,深度为奇数的节点到根的点权和,求合法的整棵树的最小点权和。

题解:对于深度为偶数的节点,将其s设为所有儿子中最小的s;如果是叶子,就将其设为父节点的s。

代码:

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

const int MAXN=200000+2;
struct HASH{
    int u;
    HASH *next;
    HASH(){}
    HASH(int _u,HASH *_next):u(_u),next(_next){}
}*tab[MAXN],mem[MAXN];
int N,cnt;
ll s[MAXN],Ans;

void Insert(int u,int v){ tab[u]=&(mem[cnt++]=HASH(v,tab[u]));}

void DFS(int x,int f,int d){
    ll b=INT_MAX;
    for(HASH *p=tab[x];p;p=p->next)
        DFS(p->u,x,d+1),b=min(b,s[p->u]);

    if(b==INT_MAX) b=s[f];
    if(b<s[f]){
        cout << -1 << endl;
        exit(0);
    }
    if(s[x]==-1) s[x]=b;

    for(HASH *p=tab[x];p;p=p->next) Ans+=s[p->u]-s[x];
}

int main(){
    cin >> N;
    for(int i=2,p;i<=N;i++){
        cin >> p;
        Insert(p,i);
    }
    for(int i=1;i<=N;i++) scanf("%lld",s+i);
/*
for(int i=1;i<=N;i++){
    cout << i << ":";
    for(HASH *p=tab[i];p;p=p->next) cout << p->u << " ";
    cout << endl;
}
*/
    DFS(1,0,1);
    cout << s[1]+Ans << endl;

    return 0;
}
View Code

 

E.Nice table

(待补)

 

F.Cookies

题意:给定一颗树,A每次可以向下移动一步;B每次可以切掉A所在节点与儿子的一条连边。A可以随时结束游戏,结束后往根走的同时,可以吃掉经过的节点的饼干,每吃一个饼干的时间与饼干所在节点有关,求在限定时间内,可以吃掉的最多的饼干。

题解:假定我们已经有了一条路径,显然吃饼干是从花费最小的开始吃,所以我们DFS,用线段树来记录路径上吃饼干的花费:用t作为角标,每个节点记录吃掉路径上[l,r]时间范围内的饼干的数量,和吃掉他们的花费。Query的过程可以参考代码。

代码:

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

const int MAXN=1000000+2;
struct HASH{
    ll u,w;
    HASH *next;
    HASH(){}
    HASH(ll _u,ll _w,HASH *_next):u(_u),w(_w),next(_next){}
}*tab[MAXN],mem[MAXN];
int N,cnt;
ll T,c[MAXN],t[MAXN],U;

//Segment Tree begin
struct NODE{
    ll l,r;
    ll s,n;
    NODE(){}
    NODE(ll _l,ll _r):l(_l),r(_r),s(0),n(0){}
}tree[6*MAXN];

void Pushup(int x){
    tree[x].n=tree[2*x].n+tree[2*x+1].n;
    tree[x].s=tree[2*x].s+tree[2*x+1].s;
}

void Build(int x,ll l,ll r){
    tree[x]=NODE(l,r);
    if(l==r) return;

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

void Update(int x,ll p,ll v){
    tree[x].n+=v,tree[x].s+=p*v;
    if(tree[x].l==tree[x].r) return;

    ll m=(tree[x].l+tree[x].r)>>1;
    if(p<=m) Update(2*x,p,v);
    else Update(2*x+1,p,v);
}

ll Query(int x,ll r){
    if(tree[x].l==tree[x].r) return min(tree[x].n,r/tree[x].l);
    if(r<tree[2*x].s) return Query(2*x,r);
    else return tree[2*x].n+Query(2*x+1,r-tree[2*x].s);
}
//Segment Tree end

void Insert(int u,int v,ll w){ tab[u]=&(mem[cnt++]=HASH(v,w,tab[u]));}

ll DFS(int x,ll r){
    if(r<=0) return 0;

    Update(1,t[x],c[x]);
    ll Ret=Query(1,r),a=0,b=0,rec;

    for(HASH *p=tab[x];p;p=p->next){
        rec=DFS(p->u,r-2*p->w);
        if(rec>a) b=a,a=rec;
        else if(rec>b) b=rec;
    }

    Update(1,t[x],-c[x]);
    if(x==1) return max(Ret,a);
    else return max(Ret,b);
}

int main(){
    cin >> N >> T;
    for(int i=1;i<=N;i++) scanf("%lld",c+i);
    for(int i=1;i<=N;i++) scanf("%lld",t+i),U=max(U,t[i]);
    for(int i=2,p,l;i<=N;i++){
        scanf("%d %d",&p,&l);
        Insert(p,i,(ll)l);
    }

    cnt=0,Build(1,1,U);
    cout << DFS(1,T) << endl;

    return 0;
}
View Code

 

posted @ 2019-03-05 17:08  WDZRMPCBIT  阅读(231)  评论(0编辑  收藏  举报