THUSC2016
补退选
Luogu
LOJ
BZOJ
比较裸。
建一棵Trie树,记录一下每个节点的\(sum\)表示经过该点的字符串个数,每次暴力插入、删除。
同时每个节点维护一个vector,记录一下这个点的\(sum\)第一次达到(超过)某个值的时间。
容易证明vector的总的元素个数是\(O(\sum|S|)\)的。总的复杂度为\(O(\sum|S|)\)。
#include<bits/stdc++.h>
using namespace std;
const int N=100007,M=60*N;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
int T=1,cnt,ans,sum[M],ch[M][10];vector<int>t[M];char s[61];
void update(int p)
{
if(sum[p]<=(int)t[p].size()) return ;
t[p].push_back(T);
}
void insert()
{
scanf("%s",s);int len=strlen(s),p=0;++sum[p],update(p);
for(int i=0,c;i<len;++i)
{
if(!ch[p][c=s[i]-'a']) ch[p][c]=++cnt;
++sum[p=ch[p][c]],update(p);
}
}
void remove()
{
scanf("%s",s);int len=strlen(s),p=0;--sum[p];
for(int i=0,c;i<len;++i) --sum[p=ch[p][c=s[i]-'a']];
}
void query()
{
scanf("%s",s);
int a=read(),b=read(),c=read(),len=strlen(s),p=0;
a=(1ll*a*abs(ans)+b)%c;
for(int i=0;i<len;++i) if(!(p=ch[p][s[i]-'a'])) return (void)(printf("%d\n",ans=-1));
if((int)t[p].size()<=a) return (void)(printf("%d\n",ans=-1));
printf("%d\n",ans=t[p][a]);
}
int main()
{
for(int m=read();T<=m;++T)
switch(read())
{
case 1:insert();break;
case 2:remove();break;
case 3:query();break;
}
}
成绩单
Luogu
LOJ
BZOJ
看到数据范围基本上区间dp没得跑了,这东西大概能够容忍\(O(n^5)\)的时间复杂度和\(O(n^4)\)的空间复杂度。(虽然感觉时间复杂度\(O(n^6)\)也完全没问题...)
那么我们就可以把有用的四个东西全部放进我们的状态。
设\(f_{l,r,x,y}\)表示\([l,r]\)区间,剩下的数在\([x,y]\)范围内(记得离散化)的最小代价。然后我们发现这东西不好表示区间全部被消掉的情况,而这正是我们需要求的,所以我们再开一个\(g_{l,r}\)表示消掉\([l,r]\)区间的最小代价。
考虑如何从\([l,r-1]\)扩展到\([l,r]\)。
针对\(w_r\)这一元素,我们有两种转移:(总的取\(\min\))
\(1.\)不管它。
\(f_{l,r,\min(w_r,x),\max(w_r,y)}\leftarrow f_{l,r-1,x,y}\)
\(2.\)在\([l,r-1]\)找一个后缀跟它一起消掉。
\(f_{l,r,x,y}\leftarrow f_{l,k,x,y}+g_{k+1,r}\ k\in[l,r)\)
同时显然有\(g_{l,r}=\min(f_{l,r,x,y}+(t_y-t_x)^2)\)。(\(t_x\)表示去重后\(x\)的原值)
最后的答案就是\(g_{1,n}\)。
注意转移顺序需要满足拓扑序,即先从小到大枚举区间长度再从左往右枚举左端点。
初值\(f_{i,i,w_i,w_i}=0,g_{i,i}=a\),其它的都是\(+\infty\)。
#include<bits/stdc++.h>
using namespace std;
int read(){int x;scanf("%d",&x);return x;}
int max(int a,int b){return a>b? a:b;}
int min(int a,int b){return a<b? a:b;}
int sqr(int x){return x*x;}
const int N=51;
int w[N],t[N],f[N][N][N][N],g[N][N];
int main()
{
int n=read(),m=n,a=read(),b=read();
for(int i=1;i<=n;++i) w[i]=t[i]=read();
sort(t+1,t+n+1),m=unique(t+1,t+n+1)-t-1,memset(f,0x3f,sizeof f),memset(g,0x3f,sizeof g);
for(int i=1;i<=n;++i) w[i]=lower_bound(t+1,t+m+1,w[i])-t,f[i][i][w[i]][w[i]]=0,g[i][i]=a;
for(int len=1,l,r,x,y,k;len<n;++len)
for(l=1,r=l+len;r<=n;++l,++r)
{
f[l][r][w[r]][w[r]]=g[l][r-1];
for(x=1;x<=m;++x) for(y=x;y<=m;++y) f[l][r][min(x,w[r])][max(y,w[r])]=min(f[l][r][min(x,w[r])][max(y,w[r])],f[l][r-1][x][y]);
for(k=l;k<r;++k) for(x=1;x<=m;++x) for(y=x;y<=m;++y) f[l][r][x][y]=min(f[l][r][x][y],f[l][k][x][y]+g[k+1][r]);
for(x=1;x<=m;++x) for(y=x;y<=m;++y) g[l][r]=min(g[l][r],f[l][r][x][y]+a+b*sqr(t[y]-t[x]));
}
printf("%d",g[1][n]);
}
星露谷物语
THUSC2016的更多相关文章
- thusc2016游记&&滚粗记&&酱油记
#include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs.com/w ...
- THUSC2016 游记
浑浑噩噩地就出发了,只记得可以翘课,不知道自己要干什么去. Day 0 5点起床,到潮汕机场坐飞机.第一次坐飞机非常不爽起飞和降落时的加速度……终于还是转转地铁.动车在下午4点左右抵达目的地,西 ...
- BZOJ4896 THUSC2016补退选(trie)
字符串扔进trie,vector记录每个前缀出现次数的最大值的更新记录即可. #include<iostream> #include<cstdio> #include<c ...
- BZOJ4897 THUSC2016成绩单(区间dp)
拿走一个区间的代价只与最大最小值有关,并且如果最后一次拿走包含区间右端点的子序列一定不会使答案更劣,于是设f[i][j][x][y]为使i~j区间剩余最小值为x最大值为y且若有数剩余一定包含j的最小代 ...
- [BZOJ4897][THUSC2016]成绩单(DP)
4897: [Thu Summer Camp2016]成绩单 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 220 Solved: 132[Subm ...
- [BZOJ4896][THUSC2016]补退选(Trie)
4896: [Thu Summer Camp2016]补退选 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 653 Solved: 228[Subm ...
- 【THUSC2016】成绩单(bzoj4897)
$f(i,j,x,y)$ 表示区间 $[i,j]$中,第 $j$ 个数在最后一次操作中才消去,最后一次操作的最大值为 $x$,最小值为 $y$ 时的最小代价: $g(i,j)$ 表示区间 $[i,j] ...
- BZOJ 4896 [Thusc2016]补退选 (Trie树维护vector)
题目大意:略 这竟然是$thusc$的题... 先把询问里加入的串全拎出来,建出$Trie$树,$Trie$里每个节点都开一个$vector$记录操作标号,再记录操作数量$sum$ 然后瞎**搞搞就行 ...
- 洛谷P5335 [THUSC2016]补退选 题解
传送门 一道字典树的例题吧 先说下思路前1,2两个条件都易满足,字典树插入修改即可,第三个条件可用动态数组来实现,存下它的size表示当前有几个节点经过(即人数),其下标表示第几次出现,里面存入操作次 ...
- 【洛谷5335】[THUSC2016] 补退选(指针实现Trie)
点此看题面 大致题意: 三种操作:加入一个字符串,删除一个字符串,求最早什么时候以某个字符串为前缀的字符串个数超过给定值. \(Trie\) 这道题显然是\(Trie\)的暴力裸题. 考虑我们对于\( ...
随机推荐
- Postman实现数字签名,Session依赖, 接口依赖, 异步接口结果轮询
Script(JS)为Postman赋予无限可能 基于Postman 6.1.4 Mac Native版 演示结合user_api_demo实现 PS 最近接到任务, 要把几种基本下单接口调试和持续集 ...
- Vue小实例
最近刚学习Vue的官方文档,了解了指令.模板.组件.数据双向绑定等有关Vue的知识点.因此估摸着做点实例出来练练手. 下面介绍一个简单的例子,模拟购物车自动统计金额,效果图如下: 代码如下: < ...
- vue 复制内容到粘贴板
首先是npm安装依赖包:npm install clipboard --save 导入组件:import Clipboard from "clipboard"; html如图: c ...
- 【零基础】一文读懂CPU(从二极管到超大规模集成电路)
一.前言 我们都知道芯片,也知道芯片技术在21世纪是最重要的技术之一,但很少有人能知道芯片技术的一些细节,如芯片是如何构造的.为什么它可以运行程序.芯片又是如何被设计制造出来的等等.本文就尝试从最底层 ...
- java日期大小比较
之前有面试到两个日期的大小比较方式,现在整理一下几种方法. 例子: String beginTime=new String("2017-06-09 10:22:22"); S ...
- Go语言学习之介绍与环境搭建
Go语言第一课 一.Go语言介绍 1.什么是Go语言? Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易. Go是从2007年末由Robert Griesemer, Rob Pik ...
- 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_6-1.常用的第三方支付和聚合支付介绍
笔记 第六章 开发在线教育视频站点核心业务之从零基础接入 微信扫一扫网页支付 1.常用的第三方支付和聚合支付介绍 简介:介绍常用的第三方支付和聚合支付 1.什么是第三方支付 第 ...
- Ubuntu 安装 docker,并上传到dockerhub
一.安装Docker apt-get -y install docker.io 链接: ln -sf /usr/bin/docker.io /usr/local/bin/docker 检查docker ...
- delphi 中Adoquery ,在打开时能否让记录指针不移动? [问题点数:40分,结帖人microd]
delphi 中Adoquery ,在打开时能否让记录指针不移动?由于数据集Adoquery 时,它的针指称动会废时,能否在打开完成之前不让记录指针不移动.打开完毕之后再回复移动? 这样用:self. ...
- 启动nfs清除端口占用过程
centos7起nfs服务. 按教程执行: vim /etc/exportsyum install -y nfs-utils systemctl enable rpcbind.service syst ...