12.8 模拟赛

T1 成绩单 bzoj 4897

题目大意:

一个数列 每次可以取出连续的一段 剩下的部分自动拼接起来 直到把序列取空 代价为:

$A \times k + B \times \sum_{i=1}^k {(max_i-min_i)^2}$

求最小代价

思路:

区间$dp_{i,j,a,b}$表示把区间$[i,j]$取到剩的数在$[a,b]$之间的代价

转移的时候把区间向里缩使得被缩的数在$[a,b]$之间 在剩余的区间中枚举断点

从两边取完或者剩$[a,b]$的状态转移过来

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<complex>
10 #include<map>
11 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
12 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
13 #define ren for(register int i=fst[x];i;i=nxt[i])
14 #define Fill(x,t) memset(x,t,sizeof(x))
15 #define ll long long
16 #define Cd complex<double>
17 #define inf 2139062143
18 #define MOD 998244353
19 #define MAXN 100100
20 #define MAXM 500100
21 using namespace std;
22 inline int read()
23 {
24     int x=0,f=1;char ch=getchar();
25     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
26     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
27     return x*f;
28 }
29 int n,A,B,dp[60][60][60][60],g[MAXN],h[MAXN];
30 int ok(int x,int l,int r) {return x>=l&&x<=r;}
31 int add(int x,int y) {return x==inf&&y==inf?inf:x+y;}
32 void upd(int &x,int y) {x=min(x,y);}
33 int main()
34 {
35     n=read(),A=read(),B=read();rep(i,1,n) g[i]=h[i]=read();Fill(dp,127);
36     sort(h+1,h+n+1);int l,r,m=unique(h+1,h+n+1)-h-1;rep(i,1,n) g[i]=lower_bound(h+1,h+m+1,g[i])-h;
37     rep(i,0,n) rep(j,1,n-i) rep(a,1,m) rep(b,a,m)
38     {
39         l=j,r=i+j;while(ok(g[l],a,b)) l++;while(ok(g[r],a,b)) r--;
40         if(l>r) dp[j][i+j][a][b]=0;else if(l==r) dp[j][i+j][a][b]=A;
41         else
42         {
43             rep(k,l,r-1) upd(dp[j][i+j][a][b],add(min(dp[l][k][a][b],dp[l][k][0][0]),min(dp[k+1][r][0][0],dp[k+1][r][a][b])));
44             upd(dp[j][i+j][a][b],dp[l][r][0][0]);
45         }
46         if(dp[j][i+j][a][b]!=inf) upd(dp[j][i+j][0][0],dp[j][i+j][a][b]+A+B*(h[b]-h[a])*(h[b]-h[a]));
47     }
48     printf("%d\n",dp[1][n][0][0]);
49 }
View Code

 

T2 补退选 bzoj 4896

题目大意:

n行,每行描述一个事件;每行第一个正整数k表示事件类型:

1.如果k=1,表示选课事件,接下来一个字符串S,表示一个姓名为S的学生选了X老师的课

2.如果k=2,表示退课事件,接下来一个字符串S,表示一个姓名为S的学生退了X老师的课

3.如果k=3,表示查询事件,接下来一个字符串S以及三个非负整数a,b,c,表示X老师想知道最早在第几个事件之后,姓名以S为前缀的学生数量超过了给定的值

思路:

直接使用trie树大力模拟 对每个点开一个vector在上面二分即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define inf 2139062143
13 #define rep(i,s,t) for(register int i=(s),i__end=(t);i<=i__end;i++)
14 #define dwn(i,s,t) for(register int i=(s),i__end=(t);i>=i__end;i--)
15 #define ren(x) for(register int i=fst[x];i;i=nxt[i])
16 #define MAXN 100100
17 using namespace std;
18 inline int read()
19 {
20     int x=0,f=1;char ch=getchar();
21     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
22     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
23     return x*f;
24 }
25 int n,tr[MAXN<<6][10],sz,sum[MAXN<<6],las[MAXN<<6];
26 struct node{int id,mx;};
27 vector <node> vec[MAXN<<6];
28 char ch[65];
29 void ins(int x,int val)
30 {
31     int pos=0,len=strlen(ch+1);
32     rep(i,1,len)
33     {
34         if(!tr[pos][ch[i]-'a']) tr[pos][ch[i]-'a']=++sz;
35         pos=tr[pos][ch[i]-'a'],sum[pos]+=val;vec[pos].push_back((node){x,max(sum[pos],las[pos])});
36         las[pos]=max(sum[pos],las[pos]);
37     }
38 }
39 int query(int x)
40 {
41     int pos=0,len=strlen(ch+1);
42     rep(i,1,len) {pos=tr[pos][ch[i]-'a'];if(!pos) return -1LL;}
43     int l=0,mid,r=vec[pos].size()-1,res=-1;
44     while(l<=r) {mid=(l+r)>>1;if(vec[pos][mid].mx>x) res=mid,r=mid-1;else l=mid+1;}
45     return res<0?-1:vec[pos][res].id;
46 }
47 int main()
48 {
49     n=read();int t;ll a,b,c,las=0;
50     rep(i,1,n)
51     {
52         t=read();scanf("%s",ch+1);
53         if(t==1) ins(i,1);
54         else if(t==2) ins(i,-1);
55         else {a=read(),b=read(),c=read();a=(a*las+b)%c;printf("%lld\n",las=query(a));if(las<0) las=-las;}
56     }
57 }
58 
View Code

 

posted @ 2018-12-20 09:02  jack_yyc  阅读(170)  评论(0编辑  收藏  举报