标签:define for using 排队 mem swa 二分答案 fine 答案
这场真是无聊,搬远古原题……
xjb做了做,(居然没AK真是身败名裂)
A.教主的花园
答案明显具有可二分性,二分答案判定下就行。
#include<bits/stdc++.h> #define N 100010 using namespace std; int n,m,a[N]; inline int check(int x){ int l=1,r=n;int ret=n; while(l<=r){ int mid=(l+r)>>1; if(a[mid]<x)l=mid+1;else r=mid-1,ret=mid; } return ret; } inline int dis(int a,int b){a=a-b;if(a<0) return -a;else return a;} inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch==‘-‘)f=-1;}while(ch<‘0‘||ch>‘9‘); do{x=x*10+ch-‘0‘;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘); return f*x; } int main(){ n=read();for(int i=1;i<=n;i++)a[i]=read(); m=read();int x1,y1,x2,y2; sort(a+1,a+n+1); for(int i=1;i<=m;i++){ x1=read(),y1=read(),x2=read(),y2=read(); if((y1<0&&y2<0)||(y1>0&&y2>0)){printf("%d\n",dis(y1,y2)+dis(x1,x2));continue;} if(x1>x2)swap(x1,x2);int len=(x1+x2)>>1,pos=check(len); if(x1<=a[pos]&&a[pos]<=x2){printf("%d\n",dis(y1,y2)+dis(x1,x2));continue;} int t1=dis(a[pos],x1)+dis(a[pos],x2)+dis(y1,y2),t2=0x7fffffff,t3=0x7fffffff; if(pos>1)t2=dis(a[pos-1],x1)+dis(a[pos-1],x2)+dis(y1,y2); if(pos<n)t3=dis(a[pos+1],x1)+dis(a[pos+1],x2)+dis(y1,y2); if(t1>t2)t1=t2;if(t1>t3)t1=t3; printf("%d\n",t1); } }
教主泡嫦娥
环形上跑一下dp,四维记录状态。
#include<bits/stdc++.h> #define N 10010 #define inf 10000000000000007LL using namespace std; typedef long long ll; int a[N],n,m; ll f[N][2][2],ans=0; inline ll sqr(ll x){return x*x;} inline void dfs(){ f[0][0][1]=f[0][1][1]=inf; for(int i=1;i<=n;i++)for(int j=0;j<2;j++) if((a[i]<a[i-1])^j){ f[i][j][0]=f[i-1][j][0]+abs(a[i]-a[i-1]); f[i][j][1]=min(f[i-1][j][1],min(f[i-1][j^1][0],f[i-1][j^1][1])+m)+abs(a[i]-a[i-1]); } else{ f[i][j][0]=f[i-1][j][0]+sqr(a[i]-a[i-1]); f[i][j][1]=min(f[i-1][j][1],min(f[i-1][j^1][0],f[i-1][j^1][1])+m)+sqr(a[i]-a[i-1]); } } inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch==‘-‘)f=-1;}while(ch<‘0‘||ch>‘9‘); do{x=x*10+ch-‘0‘;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘); return f*x; } int main(){ n=read();m=read(); for(int i=0;i<n;i++)a[i]=read(); a[n]=a[0];memset(f,0,sizeof(f)); dfs(); ans=min(min(f[n][0][0],f[n][0][1]),min(f[n][1][0],f[n][1][1])); memset(f,0,sizeof(f));f[0][0][0]=inf;dfs(); ans=min(ans,f[n][1][1]-m); memset(f,0,sizeof(f));f[0][1][0]=inf;dfs(); ans=min(ans,f[n][0][1]-m); cout<<ans<<endl; }
保镖排队:
懒得写了,从网上粘一个解释下来:
于是假设当前有tot个格子,然后自己有j个儿子,因为是可放可不放于是就是C(tot+j,j),这个时候你们就会疑惑了,难道不是C(tot+j-1,j)吗,这不是才是可放可不放的公式吗,但你可能忘记了,自己虽然必须放在最前面,但是总的可放位置仍要把他算进去呀
#include<bits/stdc++.h> #define N 2010 #define yql 10007 using namespace std; int f[N][N],dp[N],g[N][N],val[N],n; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch==‘-‘)f=-1;}while(ch<‘0‘||ch>‘9‘); do{x=x*10+ch-‘0‘;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘); return f*x; } void calc(int x){ dp[x]=1;if(!g[x][0]){val[x]=1;return;} int tot=0; for(int i=g[x][0];i;i--){ calc(g[x][i]);tot+=val[g[x][i]]; dp[x]=dp[x]%yql*dp[g[x][i]]%yql*f[tot-1][val[g[x][i]]-1]%yql; } val[x]=tot+1; } inline void pre(){ f[0][0]=1; for(int i=1;i<=2000;i++){ f[i][0]=1;for(int j=1;j<=i;j++)f[i][j]=(f[i-1][j-1]+f[i-1][j])%yql; } } int main(){ pre();int T=read(); while(T--){ memset(g,0,sizeof(g));memset(dp,0,sizeof(dp));memset(val,0,sizeof(val)); n=read(); for(int i=1;i<=n;i++){ g[i][0]=read(); for(int j=1;j<=g[i][0];j++)g[i][j]=read(); } calc(1); printf("%d\n",dp[1]); } }
教主的别墅
针鸡儿丢人,身败名裂,被卡了一个点
居然都没有AK。
不放代码了,太气了。
标签:define for using 排队 mem swa 二分答案 fine 答案
原文地址:http://www.cnblogs.com/zcysky/p/7074457.html