2019_3_2 模拟赛

99 篇文章 1 订阅
58 篇文章 0 订阅

JZOJ 猫咪的进化

题目

n n n个单位时间,可以选择 v [ i ] v[i] v[i]的价值,或 v [ i ] 2 v[i]^2 v[i]2但是下一单位时间不能选择,问获得的最大价值


分析

分成三种情况,选,选平方和不选,dp即可,但是竟然卡double输入


代码

#include <cstdio>
#include <cctype>
#define rr register
#define ls (i&1)^1
using namespace std;
inline double max(double x,double y){return x>y?x:y;}
inline double iut(){
	rr int ans1=0,ans2=0,len=1,f=1; rr char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans1=(ans1<<3)+(ans1<<1)+(c^48),c=getchar();
	if (c=='.'){
		c=getchar();
		while (isdigit(c)) len=len*10,ans2=(ans2<<3)+(ans2<<1)+(c^48),c=getchar();
		return f*(ans1+ans2*1.0/len);
	}else return ans1*f;
}
double dp[2][3]; int n=iut();
signed main(){
	for (rr int i=1;i<=n;++i){
		rr double x=iut();
		dp[i&1][0]=max(dp[ls][0],max(dp[ls][1],dp[ls][2]));
		dp[i&1][1]=max(dp[ls][0],dp[ls][1])+x;
		dp[i&1][2]=max(dp[ls][0],dp[ls][1])+x*x;
	}
	printf("%.4lf",max(dp[n&1][0],max(dp[n&1][1],dp[n&1][2])));
	return 0;
}

JZOJ GF打Dota

题目

求最短路径和次短路径


分析

对于最短路径,直接spfa即可,但是对于次短路径,需要起点和终点都各跑一遍,然后枚举边求起点和终点到该边的距离,这样就能保证次短


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <deque>
#define rr register
using namespace std;
struct node{int y,w,next;}e[100001];
int n,k,dis[10001][2],v[10001],ls[10001],ans=707406378;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void spfa(int s,int p){
	dis[s][p]=0; v[s]=1;
	rr deque<int>q; q.push_back(s);
	while (q.size()){
		rr int x=q.front(); q.pop_front();
		for (rr int i=ls[x];i;i=e[i].next)
		if (dis[e[i].y][p]>dis[x][p]+e[i].w){
			dis[e[i].y][p]=dis[x][p]+e[i].w;
			if (!v[e[i].y]){
				v[e[i].y]=1;
				if (q.size()&&dis[e[i].y][p]<dis[q.front()][p]) q.push_front(e[i].y);
				    else q.push_back(e[i].y);
			}
		}
		v[x]=0;
	}	
}
signed main(){
	n=iut(); memset(dis,127/3,sizeof(dis));
	for (rr int m=iut();m;--m){
		rr int x=iut(),y=iut(),w=iut();
		e[++k]=(node){y,w,ls[x]}; ls[x]=k;
		e[++k]=(node){x,w,ls[y]}; ls[y]=k;
	}
	spfa(1,0);
	if (!iut()) return !printf("%d",dis[n][0]);
	else{
		spfa(n,1);
		for (rr int x=1;x<=n;++x)
		for (rr int i=ls[x],t;i;i=e[i].next)
		if ((t=dis[x][0]+dis[e[i].y][1]+e[i].w)>dis[n][0])
		    ans=ans<t?ans:t;
		return !printf("%d",ans);
	}
} 

JZOJ 网站计划

题目

区间最大值


分析

zkw线段树,但是我比赛的时候打错了


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int mod=2011;
int n,m,bas=1,w[530001],p[530001],ans;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
signed main(){
	n=iut(); m=iut(); while ((bas<<=1)<n+2);
    for (rr int i=1;i<=n;++i) w[bas+i]=iut(),p[bas+i]=i;
    for (rr int i=bas-1;i;--i){
    	if (w[i<<1]>w[i<<1|1]) w[i]=w[i<<1],p[i]=p[i<<1];
    	    else w[i]=w[i<<1|1],p[i]=p[i<<1|1];
	}
    for (rr int i=1;i<=m;++i){
    	rr int x=iut(),y=iut(),t=0,poi=0,l,r;
		for (l=x+bas-1,r=y+bas+1;l^r^1;l>>=1,r>>=1){
			if ((~l&1)&&t<w[l^1]) t=w[l^1],poi=p[l^1];  
			if ((r&1)&&t<w[r^1]) t=w[r^1],poi=p[r^1];
		}
		ans=(ans+t*((x+y)%mod))%mod;
		for (w[l=poi+bas]=0,l>>=1;l;l>>=1){
    	    if (w[l<<1]>w[l<<1|1]) w[l]=w[l<<1],p[l]=p[l<<1];
    	        else w[l]=w[l<<1|1],p[l]=p[l<<1|1]; 
		}
	}
	return !printf("%d",ans);
} 

JZOJ 选做作业

题目

由于作业的重要程度不同,有些作业要在做完了另外一些作业后做,选出要做的作业,来使人做完作业后心情最为高兴。


分析

那么这道题就是一个最大权闭合子图的问题,首先要用拓扑排序把环去掉,然后正点权连源点,负点权连汇点,边权是它们的绝对值,然后在原来的图边权都是无限大,这样跑一遍最小割,那剩下的图必然不连通,用正权和减去最小割即为答案


代码

#include <cstdio>
#include <cctype>
#include <queue>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
struct node{int y,w,next;}e[4001]; int s,t,n,m,tot,ans,k=1;
queue<int>tq[501],q; int dis[501],ls[501],p[501],a[501];
inline signed iut(){
    rr int ans=0,f=1; rr char c=getchar();
    while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans*f;
}
inline void add(int x,int y,int w){
	e[++k]=(node){y,w,ls[x]}; ls[x]=k;
	e[++k]=(node){x,0,ls[y]}; ls[y]=k;
}
inline signed bfs(int s){
    for (rr int i=1;i<=t;++i) dis[i]=0;
    queue<int>q; q.push(s); dis[s]=1;
    while (q.size()){
        rr int x=q.front(); q.pop();
        for (rr int i=ls[x];i;i=e[i].next)
        if (e[i].w>0&&!dis[e[i].y]){
            dis[e[i].y]=dis[x]+1;
            if (e[i].y==t) return 1;
            q.push(e[i].y);
        }
    }
    return 0;
}
inline signed dfs(int x,int now){
    if (x==t||!now) return now;
    rr int rest=0,f;
    for (rr int i=ls[x];i;i=e[i].next)
    if (e[i].w>0&&dis[e[i].y]==dis[x]+1){
        rest+=(f=dfs(e[i].y,min(now-rest,e[i].w)));
        e[i].w-=f; e[i^1].w+=f;
        if (now==rest) return rest;
    }
    if (!rest) dis[x]=0;
    return rest;
}
signed main(){
    n=iut();
    for (rr int i=1;i<=n;++i){
        a[i]=iut();
        for (rr int t=iut();t;--t)
            ++ls[i],tq[iut()].push(i);
    }
    for (rr int i=1;i<=n;++i)
        if (!ls[i]) q.push(i);
    while (q.size()){
        rr int x=q.front(),cnt=tq[x].size(); q.pop();
        for (rr int i=1;i<=cnt;++i){
            rr int y=tq[x].front();
            tq[x].pop(); tq[x].push(y);
            if (!(--ls[y])) q.push(y);
        }
    }
    for (rr int i=1;i<=n;++i)
        if (!ls[i]) p[i]=++tot;
            else ls[i]=0;
    s=tot+1,t=tot+2;
    for (rr int i=1;i<=n;++i)
    if (p[i]){
        if (a[i]<0) add(p[i],t,-a[i]);
            else add(s,p[i],a[i]),ans+=a[i];
        while (tq[i].size()){
            rr int y=tq[i].front(); tq[i].pop();
            if (p[y]) add(p[y],p[i],23333333);
        }
    }
    while (bfs(s)) ans-=dfs(s,23333333);
    return !printf("%d",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值