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); }