151021 总结

T1 模拟题,给单调队列优化dp跪了,没特判所以95

T2

我看到这个题的想法是动态规划,然后设计状态dp[i] 表示到第i个点的时候做出合法解的最小代价,其中第i个点是离散化后的点,发现状态转移是很显然的:

       Dp[i]= min (j= 1—> i-1)(k=1—>j)dp[ j]+w[i,k]可以发现对于每个相同的w,我们考虑他对答案的影响,那么只需要求出k到i-1之间dp值的最小值,那么就把dp值做进线段树里,枚举右区间,枚举所选的区间,线段树查询,这就做完了。时间复杂度O(m*logm)

考场上没时间所以输出-1骗了95


T3

首先是下面10*10的矩阵,floyd可以判断多源图集的联通性,放到这里非常方便

对于w[1],w[2],w[3]…..w[n],题目要求必须为不下降序列,由于正向考虑非常不方便(因为要越来越大可能会产生矛盾),我们可以倒着考虑。从w[n]开始,建立一个不上升子序列,这个时候可以发现当前数当然越大越好,所以可以很好地运用贪心:让当前数在满足当前情况下取最大值。

令w[i]为当前状态的限制,f[i]为当前当前状态的最大值,这个时候分为3种情况

1,w[i]的位数大于f[i],贪心的将每一位f[i]变为最大即可(因为再怎么改也不会超过w[i])

2. w[i]的位数小于f[i],直接输出NO

3,w[i]的位数等于f[i],又要分情况讨论:

{

1.     举个例子,当前限制为4567,我们可以在第一位最大取4,第二位最大取5…..

2.     再举个例子,比如限制为3000,我们可以在第一位取3,然而如果我们不能在第2,3,4位同时取0,那么第一位取3是完全没有意义的,所以第一位最大能取2

3.     再举个例子,比如当前限制为3000,我们确定了第一位为2,那么后面的数完全没有必要取0。(可以取任意数)

}

关于这种情况,我觉得dfs来实现是个很不错的方法。

另外,这道题需要高精度。

考场上写的很崩溃,最后还是AC了


//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;
	while(c<'0' || c>'9')c=getchar();
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
}
int n,h;
int a[1000010];
int main()
{
	freopen("jump.in","r",stdin);
	freopen("jump.out","w",stdout);
	R(n),R(h);
	for(int i=1;i<=n;i++)
	{
		R(a[i]);
	}
	sort(a+1,a+n+1);
	a[++n]=2147483647;
	int nowhigh=0,minn=0,maxx=0;
	for(int i=0;i<=n;i++)
	{
		if(a[i+1]>a[i]+h)
		{
			printf("%d %d %d\n",a[i],maxx,minn);
			//cerr<<clock()<<endl;
			return 0;
		}
		if(a[i+1]-nowhigh>h)nowhigh=a[i],minn++;
		maxx++;
	}
}

//Copyright(c)2015 liuchenrui
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
using namespace std;
map <ll,ll> p;
vector <ll> q[200010],d[200010];
struct node{ll val;
};node tree[600010];
ll n,m,f[200010];
struct zb{ll l;ll r;ll c;
};zb a[100010];
ll Ra[200010],tot=0;
void work(ll now,ll x,ll y,ll s,ll z)
{
	if(x==y)
	{
		tree[now].val=min(tree[now].val,z);
		return ;
	}
	ll mid=(x+y)/2;
	if(s<=mid) work(now<<1,x,mid,s,z);
	if(s>mid) work(now<<1|1,mid+1,y,s,z);
	tree[now].val=min(tree[now<<1].val,tree[now<<1|1].val);
}
ll change(ll now,ll x,ll y,ll l,ll r)
{
	ll ret=(ll)1e15;
	if(x>=l&&y<=r)
		return tree[now].val;
	ll mid=(x+y)/2;
	if(l<=mid) ret=min(ret,change(now<<1,x,mid,l,r));
	if(r>mid) ret=min(ret,change(now<<1|1,mid+1,y,l,r));
	return ret;
}
int main()
{
	freopen("proof.in","r",stdin);
	freopen("proof.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(ll i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].c);
		Ra[++tot]=a[i].l;
		Ra[++tot]=a[i].r;
	}
	sort(Ra+1,Ra+tot+1);
	unique(Ra+1,Ra+tot+1);
	for(ll i=1;i<tot;i++)
	    if(Ra[i]>=Ra[i+1])
	        tot=i;
	for(ll i=1;i<=tot;i++)
	    p[Ra[i]]=i;
	if(Ra[1]!=1||Ra[tot]!=n)
	{
		printf("-1");
		return 0;
	}
	for(ll i=1;i<=m;i++)
	{
		q[p[a[i].r]].push_back(p[a[i].l]);
		d[p[a[i].r]].push_back(a[i].c);
	}
	memset(f,127/3,sizeof(f));
	memset(tree,127/3,sizeof(tree));
	f[0]=0;
	work(1,1,tot,1,0);
    for(ll i=2;i<=tot;i++)
    {
    	for(ll j=0;j<q[i].size();j++)
    	    f[i]=min(f[i],change(1,1,tot,q[i][j],i-1)+d[i][j]);
    	work(1,1,tot,i,f[i]);
    }
    if(f[tot]>=(ll)1e15)puts("-1"),exit(0);
	else cout<<f[tot];
}

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<limits>
using namespace std;
int n;
int mp[11][11];
char w[10001][55];
char f[10001][55];
char ans[10001][55];
bool flag=false;
void dfs(int num,int now,int limit,bool lim)
{
	if(now==limit+1)
	{
		flag=true;
		return;
	}
	if(!lim)for(int i=9;i>=0;i--)
	{
		if(mp[f[num][now]-'0'][i] && i<=w[num][now]-'0')
		{
			ans[num][now]=i+'0';
			if(i==w[num][now]-'0')dfs(num,now+1,limit,0);
			else dfs(num,now+1,limit,1);
			if(flag)return;
		}
	}
	else
	{
		for(int i=9;i>=0;i--)
		{
			if(mp[f[num][now]-'0'][i])
			{
				ans[num][now]=i+'0';
				dfs(num,now+1,limit,1);
				if(flag)return;
			}
		}
	}
}
int main()
{
	freopen("forge.in","r",stdin);
	freopen("forge.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s %s",w[i]+1,f[i]+1);
	}
	for(int i=0;i<=9;i++)
		for(int j=0;j<=9;j++)
			scanf("%d",&mp[i][j]);
	for(int i=0;i<=9;i++)mp[i][i]=1;
	for(int i=0;i<=9;i++)
		for(int j=0;j<=9;j++)
			for(int k=0;k<=9;k++)
				mp[j][k]=mp[j][k]||(mp[j][i]&&mp[i][k]);
	for(int i=n;i>=1;i--)
	{
		int len1=strlen(w[i]+1),len2=strlen(f[i]+1),ret=1;
		if(len1<len2)puts("NO"),exit(0);
		if(len1>len2)
		{
			for(int p=1;p<=len2;p++)
				for(int q=9;q>=0;q--)
					if(mp[f[i][p]-'0'][q]==1)
					{
						ans[i][p]=q+'0';
						break;
					}
		}
		else
		{
			flag=false;
			dfs(i,1,len1,0);
			if(!flag)puts("NO"),exit(0);
		}
		if(i==1)break;
		len1=strlen(w[i-1]+1);
		len2=strlen(ans[i]+1);
		if(len1!=len2)ret=(len1>len2)+1;
		else
		{
			for(int j=1;j<=len1;j++)
			{
				if(ans[i][j]>w[i-1][j]){ret=1;break;}
				if(ans[i][j]<w[i-1][j]){ret=2;break;}
			}
		}
		if(ans[i][1]==0)puts("NO"),exit(0);
		if(ret==2)for(int j=1;j<=50;j++)w[i-1][j]=ans[i][j];
	}
	puts("YES");
	for(int i=1;i<=n;i++)printf("%s ",ans[i]+1);
}


你可能感兴趣的:(模拟,特判)