zoukankan      html  css  js  c++  java
  • USACO2018 DEC (Gold) (dp,容斥+哈希,最短路)

    (T1)

    传送门

    解题思路

      傻逼(dp)。。直接(ST)表处理最大值(O(n^2))艹过了。

    代码

    #include<bits/stdc++.h>
     
    using namespace std;
    const int N=10005;
     
    inline int rd(){
        int x=0,f=1; char ch=getchar();
        while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return f?x:-x;
    }
     
    int n,k,a[N],f[N],Max[N][15],lg[N];
     
    int query(int l,int r){
        int t=lg[r-l+1];
        return max(Max[l][t],Max[r-(1<<t)+1][t]);
    }
     
    int main(){
        n=rd(),k=rd();
        for(int i=1;i<=n;i++) a[i]=rd(),Max[i][0]=a[i];
        for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(int j=1;(1<<j)<=n;j++)
            for(int i=1;i+(1<<j)-1<=n;i++)
                Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
        for(int i=1;i<=n;i++)
            for(int j=max(0,i-k);j<i;j++)
                f[i]=max(f[i],f[j]+query(j+1,i)*(i-j));
        printf("%d
    ",f[n]);
        return 0;
    }
    

    (T2)

    传送门

    解题思路

      傻逼容斥。。用的哈希存状态,刚开始用的取摸哈希,发现冲突率太高,(WA)了好几次用自然溢出过了。

    代码

    #include<bits/stdc++.h>
     
    using namespace std;
    const int N=50005;
    const int base=66662333;
    const int P=131;
    typedef long long LL;
    typedef unsigned long long ull;
     
    inline int rd(){
        int x=0,f=1; char ch=getchar();
        while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return f?x:-x;
    }
     
    int n,a[N][7],tp[34];
    LL ans;
    ull hsh[N][34];
    map<ull,int> mp;
     
    void prework(int x){
        for(int i=1;i<(1<<5);i++){
            int num=0;
            for(int j=1;j<=5;j++) if((1<<(j-1))&i) 
                num++,hsh[x][i]=(hsh[x][i]+a[x][j])*base+P;
            mp[hsh[x][i]]++;
        }
    }
     
    inline void calc(int x){
        for(int i=1;i<(1<<5);i++){ 
            int num=mp[hsh[x][i]];
            if(num==1) continue;
            mp[hsh[x][i]]=1; 
            ans+=1ll*tp[i]*num*(num-1)/2;
        }
    }
     
    int main(){
        n=rd(); ans=1ll*n*(n-1)/2;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=5;j++)
                a[i][j]=rd();
            sort(a[i]+1,a[i]+6);
            prework(i);
        }
        for(int i=1;i<(1<<5);i++)
            tp[i]=(__builtin_popcount(i)&1)?(-1):1;
        for(int i=1;i<=n;i++) calc(i);
        printf("%lld
    ",ans);
        return 0;
    }
    

    (T3)

    传送门

    解题思路

      似乎想了好一会,后来发现可以类似分层图最短路做,把美味值取负数做为点权,设(dis(i)(0))表示没有到过干草棚最短路,(dis(i)(1))表示到过干草棚最短路,转移时随便讨论一下。然后最后如果(dis(i)(1)<=dis(i)(0)),说明可行。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N=100005;
    const int M=200005;
    
    inline int rd(){
    	int x=0,f=1; char ch=getchar();
    	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    
    int n,m,K,head[N],cnt,to[M<<1],nxt[M<<1],val[M<<1];
    int dis[N][3],w[N];
    bool vis[N];
    queue<int> Q;
    
    inline void add(int bg,int ed,int w){
    	to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt,val[cnt]=w;
    }
    
    void spfa(){
    	memset(dis,0x3f,sizeof(dis));
    	dis[n][0]=0; Q.push(n);
    	while(Q.size()){
    		int x=Q.front(); Q.pop(); vis[x]=0;
    		for(int i=head[x];i;i=nxt[i]){
    			int u=to[i]; 
    			if(dis[x][0]+val[i]<dis[u][0]){
    				dis[u][0]=dis[x][0]+val[i];
    				if(!vis[u]) Q.push(u),vis[u]=1;
    			}
    			if(w[u] && dis[x][0]+val[i]-w[u]<dis[u][1]){
    				dis[u][1]=dis[x][0]+val[i]-w[u];
    				if(!vis[u]) Q.push(u),vis[u]=1;
    			}
    			if(dis[x][1]+val[i]<dis[u][1]){
    				dis[u][1]=dis[x][1]+val[i];
    				if(!vis[u]) Q.push(u),vis[u]=1;
    			}
    		}
    	}
    }
    
    int main(){
    	n=rd(),m=rd(),K=rd(); int x,y,z;
    	for(int i=1;i<=m;i++){
    		x=rd(),y=rd(),z=rd();
    		add(x,y,z),add(y,x,z);
    	}
    	for(int i=1;i<=K;i++) x=rd(),w[x]=max(w[x],rd());
    	if(w[n]) {for(int i=1;i<n;i++) puts("1"); return 0;}
    	spfa();	
    	for(int i=1;i<n;i++){
    		if(dis[i][0]>=dis[i][1]) puts("1");
    		else puts("0");
    	}
    	return 0;
    }	
    
  • 相关阅读:
    第二周学习总结
    第一周学习进度总结
    淘宝网质量属性分析
    软件架构师如何工作
    寒假学习记录第十六天
    寒假学习记录第十五天
    寒假学习记录第十四天
    寒假学习记录第十三天
    三.NFS存储服务
    二.Rsync备份服务
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10526809.html
Copyright © 2011-2022 走看看