1. 程式人生 > 實用技巧 >2020牛客多校第十場 By Rynar

2020牛客多校第十場 By Rynar

C.Decrement on the Tree

硬生生地寫成了樹形dp,寫了160行

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
typedef pair<int,int> P;
const int mod=1e9+7;
const int N=2e5+10;
int n,m,k,z,ee;
int si[N],f[N],ff[N];
ll dp[N],sz[N];
int head[N],step;
int x[N],y[N];
int d[N],a[N],in[N],out[N];
int cnt=0;
int ans=0;
struct node1{
    int val,lazy;
    int l,r;
}tr[N<<2];
void pushup(int rt){
    tr[rt].val=max(tr[rt<<1].val,tr[rt<<1|1].val);
}
void putdown(int rt){
    if(tr[rt].lazy){
        tr[rt<<1].lazy=tr[rt<<1|1].lazy=tr[rt].lazy;
        tr[rt<<1].val=tr[rt<<1|1].val=tr[rt].lazy;
        tr[rt].lazy=0;
    }
}
void build(int l,int r,int rt){
    tr[rt].l=l;
    tr[rt].r=r;
    tr[rt].lazy=0;
    if (l==r){
        tr[rt].val=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    pushup(rt);
}
void update(int l,int r,int add,int rt){
    if (l<=tr[rt].l&&r>=tr[rt].r){
        tr[rt].lazy=add;
        tr[rt].val=add;
        return;
    }
    putdown(rt);
    if(l<=tr[rt<<1].r)
        update(l,r,add,rt<<1);
    if(r>=tr[rt<<1|1].l)
        update(l,r,add,rt<<1|1);
    pushup(rt);
}
int query(int l,int r,int rt){
    if(l==tr[rt].l&&r==tr[rt].r)
        return tr[rt].val;
    putdown(rt);
    if(l>=tr[rt<<1|1].l)
        return query(l,r,rt<<1|1);
    else if(r<=tr[rt<<1].r)
        return query(l,r,rt<<1);
    else
        return max(query(l,tr[rt<<1].r,rt<<1),query(tr[rt<<1|1].l,r,rt<<1|1));
}
struct node{
    int to,n,cap;
}e[N<<1];
void add(int x,int y,int v){
    e[step].to=y;
    e[step].cap=v;
    e[step].n=head[x];
    head[x]=step++;
}
void dfs(int x,int fa){
    sz[x]=dp[x]=si[N]=0;
    f[x]=fa;
    for (int i=head[x];~i;i=e[i].n){
        int v=e[i].to;
        if (v==fa)continue;
        ff[v]=i;
        dfs(v,x);
        si[x]=max(si[x],e[i].cap);
        if (sz[v]>e[i].cap){
            ll t=max(si[v]-e[i].cap,0ll),r=sz[v]-e[i].cap;
            if (t>r/2)dp[x]+=t;
            else dp[x]+=(r+1)/2;
        }
        sz[x]+=e[i].cap;
    }
}
void update1(int x,int fa,int k,int son){
    ll pp=0;
    int v=son;
    if (sz[v]>e[k*2-1].cap){
        ll t=max(si[v]-e[k*2-1].cap,0ll),r=sz[v]-e[k*2-1].cap;
        if (t>r/2)pp-=t;
        else pp-=(r+1)/2;
    }
    if (x!=1&&e[ff[x]].cap<sz[x]){
        ll t=max(si[x]-e[ff[x]].cap,0ll),r=sz[x]-e[ff[x]].cap;
        if (t>r/2)pp-=t;
        else pp-=(r+1)/2;
    }
    sz[x]-=ee;sz[x]+=z;
    e[k*2-1].cap=z;e[k*2-2].cap=z;
    if (sz[v]>e[k*2-1].cap){
        ll t=max(si[v]-e[k*2-1].cap,0ll),r=sz[v]-e[k*2-1].cap;
        if (t>r/2)pp+=t;
        else pp+=(r+1)/2;
    }
    update(d[k],d[k],z,1);
    si[x]=query(in[x],out[x],1);
    if (x!=1&&e[ff[x]].cap<sz[x]){
        ll t=max(si[x]-e[ff[x]].cap,0ll),r=sz[x]-e[ff[x]].cap;
        if (t>r/2)pp+=t;
        else pp+=(r+1)/2;
    }
    ans+=pp;
}
ll query1(ll x){
    if (si[1]>=sz[1]/2){
        return x+si[1];
    }
    else return x+(sz[1]+1)/2;
}
signed main(){
    int T,q;
    step=0;
    memset(head,-1,sizeof head);
    scanf("%lld%lld",&n,&q);
    for (int i=1;i<n;i++){
        scanf("%lld%lld%lld",&x[i],&y[i],&z);
        add(x[i],y[i],z);add(y[i],x[i],z);
    }
    dfs(1,0);
    cnt=0;
    for (int i=1;i<=n;i++){
        in[i]=cnt+1;
        for (int j=head[i];~j;j=e[j].n){
            if (e[j].to==f[i])continue;
            d[((j|1)+1)/2]=++cnt;
            a[cnt]=e[j].cap;
        }
        out[i]=cnt;
    }
    build(1,cnt,1);
    ans=0;
    for (int i=1;i<=n;i++)ans+=dp[i];
    printf("%lld\n",query1(ans));
    while(q--){
        scanf("%lld%lld",&k,&z);
        int now=x[k],u=y[k];
        if (f[x[k]]==y[k])now=y[k],u=x[k];
        ee=e[k*2-1].cap;
        update1(now,f[now],k,u);
        printf("%lld\n",query1(ans));
    }
    return 0;
}

I.Tournament

賽時沒寫出來。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300+10;
int n,m,k;
int a[N][N];
signed main(){
    int T;
    scanf("%d",&T);
    while (T--){
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
                a[i][j]=0;
        for (int i=2;i<=n;i++){
            for (int j=1;j<=min(i-1,n-i);j++){
                printf("%d %d\n",j,i);
                a[j][i]=1;
            }
        }
        for (int i=1;i<=n-1;i++){
            for (int j=i+1;j<=n;j++){
                if(!a[i][j])printf("%d %d\n",i,j);
            }
        }
    }
    return 0;
}