zoukankan      html  css  js  c++  java
  • 12.8 模拟赛

    T1 成绩单 bzoj 4897

    题目大意:

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

    $A imes k + B imes 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
    ",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
    ",las=query(a));if(las<0) las=-las;}
    56     }
    57 }
    58 
    View Code
  • 相关阅读:
    设计若干个函数, ①删除除空格、英文逗号、句号、问号、感叹号之外的所有字符; ②两个英文单词之间的空格多于1个的,把多余的删去; ③检测每句首字母是否为大写字母,若不是,将其转换为大写字母; 检测句中除首字母外是否有大写字母,若有,将其转化为小写字母。
    在一个无序整数数组中,找出连续增长片段最长的一段, 增长步长是1。Example: [3,2,4,5,6,1,9], 最长的是[4,5,6]
    linux常用命令
    linux下硬盘分区/格式化/挂载
    Solr集群搭建
    redis集群搭建手册
    免费论文查重
    log4 配置日志文件变量名
    sqlserver 属性 DefaultFullTextLanguageLcid 不可用
    iis 0x80070032 Cannot read configuration file because it exceeds the maximum file size
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/10096186.html
Copyright © 2011-2022 走看看