题目:https://loj.ac/problem/2291

想了线段树合并的做法。就是用线段树维护 trie 的每个点在各种时间的操作。

然后线段树合并一番,线段树维护前缀最大值,就是维护最大子段和的套路,记录区间和、前缀 max 。查询的时候,因为当前区间只记录了自己区间内部的前缀 max 值,所以要加一个 pr 表示该区间前面的区间和。

空间可能爆? RE 就没管。后来发现是 go[ ][ ] 开成 N 而非 M 了。这个做法还是可过的。

注意强制在线的 ans 是带绝对值的。注意 mx 的初值是 0 而非 -INF 因为可以不选。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls Ls[cr]
#define rs Rs[cr]
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=1e5+,M=6e6+,M2=2e7+;//mention
int n,cnt=,go[M][],rt[M],qnt;//M not N!!!
int tot,Ls[M2],Rs[M2],sm[M2],mx[M2]; char ch[];
struct Node{ int a,b,c,t;char s[];}q[N];
int nwnd(int pr)
{
int cr=++tot; ls=Ls[pr]; rs=Rs[pr];
sm[cr]=sm[pr]; mx[cr]=mx[pr]; return cr;
}
void pshp(int cr)//ini mx is 0!!(can choosen't)
{
mx[cr]=Mx(mx[ls],sm[ls]+mx[rs]);
sm[cr]=sm[ls]+sm[rs];
}
void ins(int l,int r,int &cr,int p,int k)
{
if(!cr)cr=++tot;
if(l==r){sm[cr]=mx[cr]=k;return;}
int mid=l+r>>;
if(p<=mid)ins(l,mid,ls,p,k);
else ins(mid+,r,rs,p,k);
pshp(cr);
}
void ins(int t,int k)
{
int cr=,len=strlen(ch+);
for(int i=,d;i<=len;i++)
{
d=ch[i]-'a';
if(!go[cr][d])go[cr][d]=++cnt;
cr=go[cr][d];
}
ins(,n,rt[cr],t,k);
}
void mrg(int l,int r,int &cr,int pr)
{
if(!pr)return; if(!cr){cr=pr;return;}
cr=nwnd(cr); int mid=l+r>>;
mrg(l,mid,ls,Ls[pr]); mrg(mid+,r,rs,Rs[pr]);
pshp(cr);
}
void dfs(int cr)
{
for(int i=,v;i<;i++)
if(v=go[cr][i])
{
dfs(v);
mrg(,n,rt[cr],rt[v]);
}
}
int qry(int l,int r,int cr,int R,int lm,int pr)
{
if(pr+mx[cr]<=lm)return -; if(l==r)return l;
int mid=l+r>>;
if(mid>=R)return qry(l,mid,ls,R,lm,pr);
if(pr+mx[ls]>lm)return qry(l,mid,ls,R,lm,pr);
return qry(mid+,r,rs,R,lm,pr+sm[ls]);
}
int qry(int bh,int lm)
{
int cr=,len=strlen(q[bh].s+);
for(int i=,d;i<=len;i++)
{
d=q[bh].s[i]-'a';
if(!go[cr][d])return -;//-1 not 0!!!!!
cr=go[cr][d];
}
return qry(,n,rt[cr],q[bh].t,lm,);
}
int main()
{
n=rdn();
for(int i=,op;i<=n;i++)
{
op=rdn();
if(op==||op==)
{
scanf("%s",ch+);
ins(i,(op==?:-));
}
else
{
qnt++; scanf("%s",q[qnt].s+);
q[qnt].a=rdn(); q[qnt].b=rdn();
q[qnt].c=rdn(); q[qnt].t=i;
}
}
dfs(); int ans=;
for(int i=;i<=qnt;i++)
{
if(ans<)ans=-ans;//////
int k=((long long)q[i].a*ans+q[i].b)%q[i].c;
ans=qry(i,k);
printf("%d\n",ans);
}
return ;
}

看了题解,原来 trie 每个节点开 vector 存 “超过某个值的最早时间” 即可。也不用往上合并,往下走的时候路径上的 vector 全加上即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=1e5+,M=N*;
int n,go[M][],tot=,ct[M],ans; char ch[];
vector<int> vt[M];
void ins(int t,int k)
{
int cr=,len=strlen(ch+);
for(int i=,d;i<=len;i++)
{
d=ch[i]-'a';
if(!go[cr][d])go[cr][d]=++tot;
cr=go[cr][d]; ct[cr]+=k;
if(ct[cr]>vt[cr].size())
vt[cr].pb(t);
}
}
void qry(int k)
{
int cr=,len=strlen(ch+);
for(int i=,d;i<=len;i++)
{
d=ch[i]-'a';
if(!go[cr][d]){ans=-;printf("%d\n",ans);return;}
cr=go[cr][d];
}
if(vt[cr].size()<=k)ans=-;
else ans=vt[cr][k];
printf("%d\n",ans);
}
int main()
{
n=rdn();
for(int i=,op;i<=n;i++)
{
op=rdn();scanf("%s",ch+);
if(op==||op==)ins(i,(op==?:-));
else
{
int a=rdn(),b=rdn(),c=rdn();
if(ans<)ans=-ans;
int k=((long long)a*ans+b)%c;
qry(k);
}
}
return ;
}

LOJ 2991 「THUSC 2016」补退选——trie+线段树合并或vector的更多相关文章

  1. 【LOJ】#2291. 「THUSC 2016」补退选

    题解 在trie树上开vector记录一下这个前缀出现次数第一次达到某个值的下标,以及记录一下现在这个前缀有多少个 为什么thusc有那么水的题--是为了防我这种cai ji爆零么= = 代码 #in ...

  2. loj2291 「THUSC 2016」补退选

    ref pkusc 快到了,做点 thusc 的题涨涨 rp-- #include <iostream> #include <cstring> #include <cst ...

  3. loj 2292「THUSC 2016」成绩单

    loj 看着就很区间dp,所以考虑求\(f_{i,j}\)表示区间\([i,j]\)的答案.注意到贡献答案的方式是每次选一个连续段,拿走后剩下的段拼起来继续段,所以转移就考虑从最后一次选的方法转移过来 ...

  4. LOJ 2292 「THUSC 2016」成绩单——区间DP

    题目:https://loj.ac/problem/2292 直接 DP 很难做,主要是有那种 “一个区间内部有很多个别的区间” 的情况. 自己想了一番枚举 max-min 的最大限制,然后在该基础上 ...

  5. 2018.10.27 loj#2292. 「THUSC 2016」成绩单(区间dp)

    传送门 g[i][j][k][l]g[i][j][k][l]g[i][j][k][l]表示将区间l,rl,rl,r变成最小值等于kkk,最大值等于lll时的花费的最优值. f[i][j]f[i][j] ...

  6. LOJ2537. 「PKUWC2018」Minimax [DP,线段树合并]

    传送门 思路 首先有一个\(O(n^2)\)的简单DP:设\(dp_{x,w}\)为\(x\)的权值为\(w\)的概率. 假设\(w\)来自\(v1\)的子树,那么有 \[ dp_{x,w}=dp_{ ...

  7. 「POI2011 R2 Day2」Tree Rotations【线段树合并】

    题目链接 [BZOJ] [洛谷] [LOJ] 题解 由于是前序遍历,那么讨论一棵树上的逆序对的情况. 两个节点都在左子树上 两个节点都在右子树上 两个节点分别在不同的子树上. 前两种情况其实也可以归结 ...

  8. 【LOJ】#2292. 「THUSC 2016」成绩单

    题解 神仙dp啊><(也有可能是我菜) 我们发现,想要拿一段区间的话,只和这个区间的最大值和最小值有关系,那么我们考虑,如果一个区间[l,r]我们拿走了一些数后,使它的最小值是a,最大值是 ...

  9. LOJ#2799. 「CCC 2016」生命之环

    题意 给你一个 \(n\) 个 \(\rm 01\) 组成的环,每次操作之后每个位置为1当且仅当他的左右恰好有1个1.输出进行 \(T\) 次操作之后的环. \(n\leq 10^5, T\leq 1 ...

随机推荐

  1. vue+iview实现table和分页及与后台数据交互

    最近在项目中遇到使用table分页的功能,所以分享出来给大家希望能够对大家有帮助,话不多说直接上代码 <template> <div> <Table :columns=& ...

  2. FileProvider 添加二级目录

    我们在做Android N升级适配的时候 传统的Intent调用文件的方式会被认为不安全的 然后系统需要让我们使用更加安全的FileProvider的方法去构建intent请求 如 拍照,安装新的ap ...

  3. 7.4 GRASP原则四:控制器 Controller

    4.GRASP原则四:控制器 Controller  What first object beyond the UI layer receives and co-ordinates (control ...

  4. JavaScript基础三

    1.10 关于DOM的事件操作 1.10.1 JavaScript的组成 JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数. ...

  5. Android测试(四)——内容供应器泄露

    内容供应器:用来存储和查询应用程序中的数据或来自电话的数据,所有内容供应器都具有唯一的统一的资源标识符(URI)以便被识别和查询. 内容供应期命名惯例:以content://开始 当Android A ...

  6. 如果SQL Server 配置管理器没有找到就代表安装失败?

    如果SQL Server 配置管理器没有找到就代表安装失败? 2017-05-09 17:58 124人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. 首先,只要你 ...

  7. 关于WebUpload插件的使用

    上传的路径地址: 删除图片时也应该注意: unlink('/Upload/1.jpg')删除不了 unlink('./Upload/1.jpg')可以删除. 也就是说,绝对路径删除不了  相对路径可以 ...

  8. 剑指Offer 31. 整数中1出现的次数(从1到n整数中1出现的次数) (其他)

    题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...

  9. 关于idea的debug

    idea的debug真的是超级好用哎.分享几个今天学会的新方式: 1.右键会发现此选项 ,点击出现 在输入框中输入,可以通过某些公式单独计算. 2.点击属性值,右键点击set values 会出现一个 ...

  10. UITabView使用详解

    在开发iphone的应用时基本上都要用到UITableView,这里讲解一下UITableView的使用方法及代理的调用情况 - (void)viewDidLoad { [super viewDidL ...