题目及数据:http://pan.baidu.com/s/1jGBoL4U
第一题:
由于整个数列必须是波动的,那么这个数列只有两种形态
o o o
o o o
o o o
o o o
这两种dp基本上没有区别,总的都可以写为dp[i][j]=max{dp[i-1][k]+w[i][j]} (k随j以及形态变化)
不过坑人的是 由于数列是环,所以首位必须也满足波动的性质。
当时是把第一位移到了n+1位,然后dp[n+1]-dp[1]的。。不过TMD好像没有任何区别T_T
所以只需要考虑第一位填什么,后面直接dp就行
第二题
对于第i个跳转器,记g[i]=i+a[i],它可以跳的范围是[1,g[i]],那么这个跳转器的唯一价值就应该是g[i]。
考虑当前需要k步才能跳到终点的跳转器有{ai|a1,a2,a3,am}(a1<a2<a3<...<am) 那么这个集合唯一有价值的也只有a1(最小)
那么记录下K步的最小值Min之后,在做第k+1步的时候,只要把还没踢出去的跳转器中>=Min的构成一个集合,再取最小值即可。
那么问题来了,蓝色部分显然需要数据结构来维护,Set、Splay都可以。。考场上写set,
不过妈蛋的是,对于set<pair<int,int>>的cmp。。我写的是first<first||first==frist&&second<second
不知道有什么问题? 就是错了。。 T_T
但是分析到这。。如果稍微再多想想,
就会发现对于每个k步可以跳完的集合X_k,以及k+1步跳完的集合X_k+1,
不难发现X_k的最小值>X_k+1的最大值,那么就好办了。。O(nlogn)排序之后从后往前一次扫描即可。

1 #include<set> 2 #include<queue> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 using namespace std; 9 const int N = 100010; 10 #define For(i,n) for(int i=1;i<=n;i++) 11 #define Rep(i,l,r) for(int i=l;i<=r;i++) 12 13 int n,W[N][4]; 14 long long ans,dp[N][4]; 15 16 void read(int &v){ 17 char ch=getchar(); 18 while(ch>'9'||ch<'0') ch=getchar(); 19 int num=0; 20 while(ch>='0'&&ch<='9'){ 21 num=num*10+ch-'0'; 22 ch=getchar(); 23 } 24 v=num; 25 } 26 27 void Dp1(int equal,int state){ 28 memset(dp,0,sizeof(dp)); 29 dp[1][state]=W[1][state]; 30 Rep(i,2,n){ 31 if(i%2==equal) 32 For(j,2) 33 Rep(k,j+1,3) 34 dp[i][j]=max(dp[i][j],dp[i-1][k]+W[i][j]); 35 else 36 Rep(j,2,3) 37 For(k,j-1) 38 dp[i][j]=max(dp[i][j],dp[i-1][k]+W[i][j]); 39 } 40 if(state==2) ans=max(ans,dp[n][3]); 41 else ans=max(max(dp[n][3],dp[n][2]),ans); 42 } 43 44 void Dp2(int equal,int state){ 45 memset(dp,0,sizeof(dp)); 46 dp[1][state]=W[1][state]; 47 Rep(i,2,n){ 48 if(i%2==0) 49 For(j,2) 50 Rep(k,j+1,3) 51 dp[i][j]=max(dp[i][j],dp[i-1][k]+W[i][j]); 52 else 53 Rep(j,2,3) 54 For(k,j-1) 55 dp[i][j]=max(dp[i][j],dp[i-1][k]+W[i][j]); 56 } 57 if(state==2) ans=max(ans,dp[n][1]); 58 else ans=max(ans,max(dp[n][2],dp[n][1])); 59 } 60 61 int main(){ 62 freopen("garden.in","r",stdin); 63 freopen("garden.out","w",stdout); 64 read(n); 65 For(i,n){ 66 read(W[i][1]);read(W[i][2]);read(W[i][3]); 67 } 68 Dp1(1,1);Dp1(1,2); 69 Dp2(0,2);Dp2(0,3); 70 cout<<ans<<endl; 71 return 0; 72 }

1 #include<set> 2 #include<queue> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 using namespace std; 9 const int N = 100010; 10 #define For(i,n) for(int i=1;i<=n;i++) 11 #define Rep(i,l,r) for(int i=l;i<=r;i++) 12 13 struct segs{ 14 int l,r; 15 }A[N]; 16 17 bool cmp(segs A,segs B){ 18 return A.r>B.r||A.r==B.r&&A.l>B.l; 19 } 20 21 int Ans[N],n,m,tcur,Times=1; 22 23 int main(){ 24 freopen("park.in","r",stdin); 25 freopen("park.out","w",stdout); 26 scanf("%d%d",&n,&m); 27 For(i,n) { 28 scanf("%d",&A[i].r); 29 A[i].l=i;A[i].r+=A[i].l; 30 } 31 sort(A+1,A+n+1,cmp); 32 int Lim=n+1,TLim=n; 33 For(i,n){ 34 if(A[i].r<Lim){ 35 ++Times; 36 Lim=TLim; 37 TLim=n; 38 } 39 Ans[A[i].l]=Times; 40 TLim=min(A[i].l,TLim); 41 } 42 For(i,m-1){ 43 scanf("%d",&tcur); 44 printf("%d ",Ans[tcur]); 45 } 46 scanf("%d",&tcur); 47 printf("%d ",Ans[tcur]); 48 return 0; 49 }