补题(队内训练)

http://icpc.njust.edu.cn/Contest/6258/I/
Tree DP 读题
Code:

#include <bits/stdc++.h>
using namespace std;
int n,x,y;
vector<int>g[50008];
int dp[50008][2];
int v[50008];
int tag[50008];
int ans=0;
void dfs(int u,int flag){
    //cout<<u<<endl;
    flag^=tag[u];
    if(flag)v[u]=-v[u];
    if(u==0){
        for(int i=0;i<g[u].size();i++){
            dfs(g[u][i],flag);
            ans+=dp[g[u][i]][0];
        }
        return ;
    }
    else {
        int c=x;
        if(tag[u])c=y;
        int s00=v[u],s01=-v[u]-c;
        int s10=-v[u],s11=v[u]-c;
        for(int i=0;i<g[u].size();i++){
            dfs(g[u][i],flag);
            int to=g[u][i];
            s00+=dp[to][0];
            s01+=dp[to][1];
            s10+=dp[to][1];
            s11+=dp[to][0];
        }
        dp[u][0]=max(s00,s01);
        dp[u][1]=max(s10,s11);
    }
}
int main(){
    while(~scanf("%d%d%d",&n,&x,&y)){
        for(int i=1;i<=n;i++){
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            v[i]=a;
            if(d)v[i]=-v[i];
            g[b].push_back(i);
            tag[i]=c;
        }
        ans=0;
        dfs(0,0);
        if(ans<0)printf("HAHAHAOMG\n");
        else printf("%d\n",ans);
        for(int i=0;i<=n;i++)g[i].clear();
    }
}

http://icpc.njust.edu.cn/Contest/6263/I/
三维偏序 CDQ分治
Code:

#include <bits/stdc++.h>
using namespace std;
int n,m;
map<int,int>ma;
map<int,int>tim;
struct node{
    int a,b,c,v,id;
}rec[100003],tmp[100003],b[100003];
int ans[100003];
int v[100003];
int tot,ttot;
bool cmp1(node a,node b){
    if(a.a!=b.a)return a.a>b.a;
    if(a.b!=b.b)return a.b>b.b;
    return a.c>b.c;
}
bool cmp2(node a,node b){
    if(a.b!=b.b)return a.b>b.b;
    return a.c>b.c;
}
void debug(){
    for(int i=1;i<=tot;i++){
        for(int j=1;j<=tot;j++){
            if(j==i)continue;
            if(rec[j].a>=rec[i].a&&rec[j].b>=rec[i].b&&rec[j].c>=rec[i].c)ans[rec[i].id]++;
        }
    }
}
int c[100003];
int lowbit(int x){
    return x&(-x);
}
int query(int x){
    int ret=0;
    while(x<=100000){
        ret+=c[x];
        x+=lowbit(x);
    }
    return ret;
}
void update(int x){
    while(x){
        c[x]++;
        x-=lowbit(x);
    }
}
void reset(int p){
    while(p){
        c[p]=0;
        p-=lowbit(p);
    }
}

void cdq(int l, int r){
    if(l==r)return;
    int m=(l+r)/2;
    cdq(l, m);
    cdq(m+1, r);
    for(int i=l;i<=r;i++){
        b[i]=rec[i];
    }
    sort(b+l, b+m+1, cmp2);
    sort(b+m+1, b+r+1, cmp2);
    int j=l;
    for(int i=m+1;i<=r;i++){
        while(j<=m&&b[j].b>=b[i].b){
            update(b[j++].c);
        }
        ans[b[i].id]+=query(b[i].c);
    }
    for(int i=l;i<=m;i++)reset(b[i].c);
    return;
}
int main(){
    int T;
    scanf("%d",&T);
    for(int tt=1;tt<=T;tt++){
        memset(ans,0,sizeof(ans));
        memset(c,0,sizeof(c));
        scanf("%d%d",&n,&m);
        ma.clear();
        tim.clear();
        for(int i=1;i<=n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            if(ma.find(b)==ma.end()||ma[b]<a){
                ma[b]=a;
                tim[b]=1;
            }
            else if(ma[b]==a){
                tim[b]++;
            }
        }
        tot=0,ttot=0;
        for(int i=1;i<=m;i++){
            int c,d,e;
            scanf("%d%d%d",&c,&d,&e);
            if(ma.find(e)==ma.end())continue;
            ++ttot;
            tmp[ttot].a=c;
            tmp[ttot].b=d;
            tmp[ttot].c=ma[e];
            tmp[ttot].v=tim[e];
            tmp[ttot].id=tot;
        }
        sort(tmp+1,tmp+1+ttot,cmp1);
        for(int i=1;i<=ttot;i++){
            if(tot&&tmp[i].a==rec[tot].a&&tmp[i].b==rec[tot].b&&tmp[i].c==rec[tot].c)rec[tot].v+=tmp[i].v;
            else {
                ++tot;
                rec[tot]=tmp[i];
                rec[tot].id=tot;
            }
        }
        for(int i=1;i<=tot;i++){
            v[i]=rec[i].v;
        }

        sort(rec+1,rec+1+tot,cmp1);
        cdq(1,tot);
        int ret=0;
        for(int i=1;i<=tot;i++){
            if(!ans[i]){
                ret+=v[i];
            }
        }
        printf("Case #%d: %d\n",tt,ret);
    }
}

http://icpc.njust.edu.cn/Contest/6263/K/
Mask DP
Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll a[6];
ll dp[20005][35][6];
ll fac[20005];
ll fav[20005];
ll power(ll n,ll p){
    ll ans=1;
    ll base=n;
    while(p){
        if(p&1){
            ans=ans*base%mod;
        }
        base=base*base%mod;
        p>>=1;
    }
    return ans;
}
ll inv(ll x){
    return power(x,mod-2);
}
ll C(ll x,ll y){
    if(y==0)return 1;
    return (fac[x]*fav[y]%mod)*fav[x-y]%mod;
}
ll cnt(ll x){
    return __builtin_popcount(x);
}
void debug(){
    ll x,y;
    while(cin>>x>>y){
        cout<<C(x,y)<<endl;
    }
}
int main(){
    fac[0]=1;
    fav[0]=1;
    for(ll i=1;i<=20000;i++){
        fac[i]=fac[i-1]*i%mod;
        fav[i]=inv(fac[i]);
    }
    ll T;
    scanf("%lld",&T);
    for(ll tt=1;tt<=T;tt++){
        ll n;
        scanf("%lld",&n);
        for(ll i=0;i<5;i++){
            scanf("%lld",&a[i]);
        }
        memset(dp,0,sizeof(dp));
        for(ll k=1;k<=5;k++){
            dp[0][0][k]=1;
            for(ll i=1;i<=n;i++){
                for(ll j=0;j<32;j++){
                    dp[i][j][k]+=dp[i-1][j][k]*(5-k+cnt(j));
                    dp[i][j][k]%=mod;
                    for(ll l=0;l<5;l++){
                        if(j&(1<<l)){
                            if(i-a[l]-1<0)continue;
                            dp[i][j][k]+=dp[i-a[l]-1][j^(1<<l)][k]*C(i-1,a[l]);
                            dp[i][j][k]%=mod;
                        }
                    }
                }
            }
        }
        ll ans1=power(5,n);
        for(ll k=1;k<=5;k++){
            ll op=1;
            if(k%2)op=-1;
            for(ll j=0;j<32;j++){
                if(cnt(j)==k){
                    ans1+=(op*dp[n][j][k]+mod);
                    ans1%=mod;
                }
            }
        }

        ll ans2;
        if(a[0]==0){
            ans2=0;
        }
        else {
            n--;
            a[0]--;
            memset(dp,0,sizeof(dp));
            for(ll k=1;k<=5;k++){
                dp[0][0][k]=1;
                for(ll i=1;i<=n;i++){
                    for(ll j=0;j<32;j++){
                        dp[i][j][k]+=dp[i-1][j][k]*(5-k+cnt(j));
                        dp[i][j][k]%=mod;
                        for(ll l=0;l<5;l++){
                            if(j&(1<<l)){
                                if(i-a[l]-1<0)continue;
                                dp[i][j][k]+=dp[i-a[l]-1][j^(1<<l)][k]*C(i-1,a[l]);
                                dp[i][j][k]%=mod;
                            }
                        }
                    }
                }
            }
            ans2=power(5,n);
            for(ll k=1;k<=5;k++){
                ll op=1;
                if(k%2)op=-1;
                for(ll j=0;j<32;j++){
                    if(cnt(j)==k){
                        ans2+=(op*dp[n][j][k]+mod);
                        ans2%=mod;
                    }
                }
            }
        }
        ans1=(ans1-ans2+mod)%mod;
        printf("Case #%d: %lld\n",tt,ans1);
    }
}

http://icpc.njust.edu.cn/Contest/6265/D/
Tree DP DSU启发式合并

#include <bits/stdc++.h>
using namespace std;
const int inf=1e9+7;
struct node{
    int p,v;
};
bool operator<(const node& a,const node& b){
    return a.p<b.p;
}
multiset<node>g[100003];
int n,m;
int bar[100003];
int mi[100003];
int ma[100003];
int id[100003];
int dp[100003];
int sum[100003];
int f[100003];
bool cmp(int x,int y){
    return bar[x]<bar[y];
}
int getfa(int u){
    if(f[u]==u)return u;
    return f[u]=getfa(f[u]);
}
void Union(int u,int v){
    u=getfa(u);
    v=getfa(v);
    if(g[u].size()<g[v].size())swap(u,v);
    int tma=max(ma[u],ma[v]);
    int tmi=min(ma[u],ma[v]);
    ma[u]=tma;
    mi[u]=tmi;
    sum[u]+=sum[v];
    dp[u]=max(dp[u]+dp[v],sum[u]);
    for(auto it=g[v].begin();it!=g[v].end();it++){
        g[u].insert(*it);
    }
    auto it=g[u].upper_bound((node){mi[v],0});
    for(;it!=g[u].end();it++){
        if((it->p)>mi[u])break;
        sum[u]+=it->v;
        dp[u]=max(dp[u],sum[u]);
    }
    f[v]=u;
}
int main(){
    int T;
    cin>>T;
    for(int tt=1;tt<=T;tt++){
        cin>>n>>m;
        bar[0]=inf;
        bar[n]=inf;
        for(int i=1;i<n;i++){
            scanf("%d",&bar[i]);
            id[i]=i;
        }
        for(int i=1;i<=n;i++){
            f[i]=i;
            mi[i]=min(bar[i-1],bar[i]);
            ma[i]=max(bar[i-1],bar[i]);
        }
        sort(id+1,id+n,cmp);
        for(int i=1;i<=m;i++){
            int id,p,v;
            scanf("%d%d%d",&id,&p,&v);
            p++;
            if(v==0){
                v--;
            }
            g[id].insert((node){p,v});
        }
        for(int i=1;i<=n;i++){
            sum[i]=0;
            for(auto it=g[i].begin();it!=g[i].end();it++){
                sum[i]+=(it->v==-1);
            }
            auto it=g[i].begin();
            dp[i]=sum[i];
            for(;it!=g[i].end();it++){
                if((it->p)>mi[i])break;
                sum[i]+=it->v;
                dp[i]=max(dp[i],sum[i]);
            }
        }
        for(int i=1;i<n;i++){
            int l=id[i];
            int r=l+1;
            Union(l,r);
        }
        int rt=getfa(1);
        for(int i=1;i<=n;i++)g[i].clear();
        printf("Case #%d: %d\n",tt,dp[rt]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值