AmazingCounters.com

10.15 校内模拟赛 教主系列

题目及数据: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 }
T1_100(70改)
 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\n",Ans[tcur]);
48     return 0;
49 }
T2_100

 

posted @ 2014-10-16 19:20  ZJDx1998  阅读(692)  评论(0编辑  收藏  举报