1. 程式人生 > 實用技巧 >7.16 集訓總結

7.16 集訓總結

A、Layout

題目描述


分析

裸的差分約束,細節比較多

程式碼

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef long long ll;
int head[maxn],tot=1,n,m,k;
struct asd{
    int from,to,next;
    ll val;
}b[maxn];
void ad(int aa,int bb,ll cc){
    b[tot].from=aa;
    b[tot].to=bb;
    b[tot].val=cc;
    b[tot].next=head[aa];
    head[aa]=tot++;
}
ll dis[maxn];
bool vis[maxn];
queue<int> q;
int init[maxn];
ll spfa(int xx){
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(init,0,sizeof(init));
    dis[xx]=0;
    q.push(xx);
    while(!q.empty()){
        int now=q.front();
        q.pop();
        vis[now]=0;
        for(int i=head[now];i!=-1;i=b[i].next){
            int u=b[i].to;
            if(dis[u]>dis[now]+b[i].val){
                dis[u]=dis[now]+b[i].val;
                if(vis[u]==0){
                    q.push(u);
                    vis[u]=1;
                    init[u]++;
                    if(init[u]>n){
                        return -1;
                    }
                }
            }
        }
    }
    if(dis[n]==0x3f3f3f3f3f3f3f3f) return -2;
    return dis[n];
}
int main(){
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        int aa,bb;
        ll cc;
        scanf("%d%d%lld",&aa,&bb,&cc);
        if(aa<bb){
            ad(aa,bb,cc);
        } else {
            ad(bb,aa,cc);
        }
    }
    for(int i=1;i<=k;i++){
        int aa,bb;
        ll cc;
        scanf("%d%d%lld",&aa,&bb,&cc);
        if(aa>bb){
            ad(aa,bb,-cc);
        } else {
            ad(bb,aa,-cc);
        }
    }
    for(int i=1;i<n;i++){
    	ad(i+1,i,0);
    }
    for(int i=1;i<=n;i++){
    	ad(0,i,0);
    }
    if(spfa(0)==-1){
    	printf("-1\n");
    	return 0;
    }
    printf("%lld\n",spfa(1));
    return 0;
}

B、遊戲

題目描述



分析

用並差集倒序列舉

程式碼

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int f[maxn],ff[maxn],a[maxn][2],n;
int zhao(int xx,int tim){
    if(tim>n) return f[xx]=0;
    if(xx==f[xx]) return xx;
    return f[xx]=zhao(f[xx],tim+1);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=n;i++){
        int aa;
        scanf("%d",&aa);
        if(aa!=0) f[i]=ff[i]=aa;
    }
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        scanf("%d%d",&a[i][0],&a[i][1]);
        if(a[i][0]==2) f[a[i][1]]=a[i][1];
    }
    for(int i=q;i>=1;i--){
        if(a[i][0]==1) a[i][1]=zhao(a[i][1],0);
        else f[a[i][1]]=ff[a[i][1]];
    }
    for(int i=1;i<=q;i++){
        if(a[i][0]==1){
            if(a[i][1]) printf("%d\n",a[i][1]);
            else printf("CIKLUS\n");
        }
    }
    return 0;
}

C、數字

題目描述


分析

計數類DP

程式碼

#include <bits/stdc++.h>
typedef long long ll;
const int maxn=1e3+5;
const ll mod=999983;
ll n,a[maxn],dp[maxn][9*maxn],len;
char s[maxn];
int main() {
    scanf("%lld%s",&n,s+1);
    len=strlen(s+1);
    for(ll i=1;i<=len;++i){
        a[i]=s[i]-'0';
    }
    dp[0][0]=1;
    for(ll i=1;i<=n;++i){
        for(ll j=0;j<=i*9;j++){
            for(ll k=1;k<=len;k++){
                if(j>=a[k]) dp[i][j]=(dp[i][j]+dp[i-1][j-a[k]])%mod;
            }
        }
    }
    ll ans=0;
    for(ll i=0;i<=n*9;i++){
        ans=(ans+2*dp[n][i]*dp[n][i])%mod;
    }
    ll len1=(n+1)/2,len2=n/2,ans1=0,ans2=0;
    for(ll i=0;i<=len1*9;i++){
        ans1=(ans1+dp[len1][i]*dp[len1][i]%mod)%mod;
    }
    for(ll i=0;i<=len2*9;i++){
        ans2=(ans2+dp[len2][i]*dp[len2][i]%mod)%mod;
    }
    ans=(ans-ans1*ans2%mod+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

D、水站

題目描述



分析

玄學剪枝+暴力列舉

程式碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=150505;
ll yy[maxn],xz[maxn],hf[maxn],ans,n;
vector<ll> da;
vector<ll> jl;
void solve(ll now){
    jl.clear();
    ll head=now,dys=yy[now],tot=hf[now],cs;
    jl.push_back(now);
    while(head<=n){
        cs=yy[++head]+dys;
        if(cs>xz[head]){
            dys=cs;
        } else {
            dys=cs;
            tot+=hf[head];
            jl.push_back(head);
        }
        if(tot>=ans) return;
    }
    if(tot<ans){
        ans=tot;
        da.clear();
        for(int i=0;i<jl.size();i++){
            da.push_back(jl[i]);
        }
    }
}
int main(){
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++){
        scanf("%lld%lld%lld",&yy[i],&xz[i],&hf[i]);
    }
    ans=hf[n];
    da.push_back(n);
    for(ll i=1;i<n;i++){
        solve(i);
    }
    printf("%lld\n",ans);
    for(int i=0;i<da.size();i++){
        if(i==0) printf("%lld",da[i]);
        else printf(" %lld",da[i]);
    }
    printf("\n");
    return 0;
}