清橙A1484

http://www.tsinsen.com/ViewGProblem.page?gpid=A1484###

题解:

  在线插入并不好做,我们将所有操作离线,变为删除操作。

  每次询问的时候对于当前B串所在起始位置及其长度向上向下二分,然后查询区间内合法的当前A串内的匹配点即可。

用树状数组维护(不过我sb的写了线段树,后来才发现···)。

code:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #define maxn 200005
  7 using namespace std;
  8 char ch,a[maxn*3],b[maxn*3],s[maxn];
  9 int n,m,q,la,ra,lb,rb,lena,lenb,op[maxn],st[18][maxn],ans[maxn];
 10 int SA[maxn],rank[maxn],sum[maxn],height[maxn],t1[maxn],t2[maxn];
 11 bool ok;
 12 void read(int &x){
 13     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
 14     for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
 15     if (ok) x=-x;
 16 }
 17 struct seg{
 18     #define ls k<<1
 19     #define rs (k<<1)+1
 20     int val[maxn<<2];
 21     void build(int k,int l,int r){
 22         if (l==r){
 23             if (SA[l]<=ra) val[k]=1;
 24             return;
 25         }
 26         int m=(l+r)>>1;
 27         build(ls,l,m),build(rs,m+1,r);
 28         val[k]=val[ls]+val[rs];
 29     }
 30     void modify(int k,int l,int r,int x,int add){
 31         if (l==r){val[k]+=add;return;}
 32         int m=(l+r)>>1;
 33         if (x<=m) modify(ls,l,m,x,add);
 34         else modify(rs,m+1,r,x,add);
 35         val[k]=val[ls]+val[rs];
 36     }
 37     int query(int k,int l,int r,int x,int y){
 38         if (l==x&&r==y) return val[k];
 39         int m=(l+r)>>1;
 40         if (y<=m) return query(ls,l,m,x,y);
 41         else if (x<=m) return query(ls,l,m,x,m)+query(rs,m+1,r,m+1,y);
 42         else return query(rs,m+1,r,x,y);
 43     }
 44 }T;
 45 void get_SA(){
 46     int *x=t1,*y=t2,tot=0; m=255;
 47     for (int i=1;i<=n;i++) sum[x[i]=s[i]]++;
 48     for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
 49     for (int i=n;i>=1;i--) SA[sum[x[i]]--]=i;
 50     for (int len=1;tot<n;len<<=1,m=tot){
 51         tot=0;
 52         for (int i=n-len+1;i<=n;i++) y[++tot]=i;
 53         for (int i=1;i<=n;i++) if (SA[i]>len) y[++tot]=SA[i]-len;
 54         for (int i=1;i<=m;i++) sum[i]=0;
 55         for (int i=1;i<=n;i++) sum[x[y[i]]]++;
 56         for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
 57         for (int i=n;i>=1;i--) SA[sum[x[y[i]]]--]=y[i];
 58         swap(x,y),x[SA[1]]=tot=1;
 59         for (int i=2;i<=n;i++){
 60             if (y[SA[i]]!=y[SA[i-1]]||y[SA[i]+len]!=y[SA[i-1]+len]) tot++;
 61             x[SA[i]]=tot;
 62         }
 63     }
 64     for (int i=1;i<=n;i++) rank[i]=x[i];
 65 }
 66 void get_height(){
 67     for (int i=1,j=0;i<=n;i++){
 68         if (rank[i]==1) continue;
 69         while (s[i+j]==s[SA[rank[i]-1]+j]) j++;
 70         height[rank[i]]=j;
 71         if (j>0) j--;
 72     }
 73 }
 74 void prepare(){
 75     for (int i=1;i<=n;i++) st[0][i]=height[i];
 76     for (int i=1;i<=17;i++)
 77         for (int j=1;j<=n;j++){
 78             st[i][j]=st[i-1][j];
 79             if (j+(1<<(i-1))<=n) st[i][j]=min(st[i][j],st[i-1][j+(1<<(i-1))]);
 80         }
 81     T.build(1,1,n);
 82 }
 83 int calc(int l,int r){
 84     if (l>r) swap(l,r);
 85     int t=0; l++;
 86     if (l==r) return height[l];
 87     for (;l+(1<<t)<r;t++);
 88     if (l+(1<<t)>r) t--;
 89     return min(st[t][l],st[t][r-(1<<t)+1]);
 90 }
 91 int find(int s,int x,int op){
 92     int l,r,m;
 93     if (op) l=s,r=n;else l=1,r=s;
 94     while (l!=r){
 95         m=((l+r)>>1)+op;
 96         if (calc(m,s)<x){
 97             if (op) r=m-1;
 98             else l=m+1;
 99         }
100         else{
101             if (op) l=m;
102             else r=m;
103         }
104     }
105     return l;
106 }
107 int query(){
108     int x=find(rank[lb],rb-lb+1,0),y=find(rank[lb],rb-lb+1,1);
109     return T.query(1,1,n,x,y);
110 }
111 int main(){
112     scanf("%s%s",a+maxn,b+maxn);
113     la=ra=maxn,lb=rb=maxn;
114     for (;a[ra];ra++); ra--;
115     for (;b[rb];rb++); rb--;
116     read(q);
117     for (int i=1;i<=q;i++){
118         read(op[i]);
119         if (op[i]==1) a[--la]=getchar();
120         else if (op[i]==2) a[++ra]=getchar();
121         else if (op[i]==3) b[--lb]=getchar();
122         else if (op[i]==4) b[++rb]=getchar();
123     }
124     for (int i=la;i<=ra;i++) s[++n]=a[i];
125     lena=ra-la+1,la=1,ra=lena;
126     s[++n]=‘#‘;
127     int tmp=n+1;
128     lenb=rb-lb+1;
129     for (int i=lb;i<=rb;i++) s[++n]=b[i];
130     lb=tmp,rb=lb+lenb-1;
131     get_SA(),get_height(),prepare();
132     for (int i=1;i<lenb;i++) T.modify(1,1,n,rank[ra--],-1);
133     for (int i=q;i>=1;i--){
134         if (op[i]==1) T.modify(1,1,n,rank[la++],-1);
135         else if (op[i]==2) T.modify(1,1,n,rank[ra--],-1);
136         else if (op[i]==3) T.modify(1,1,n,rank[++ra],1),lb++;
137         else if (op[i]==4) T.modify(1,1,n,rank[++ra],1),rb--;
138         else ans[i]=query();
139     }
140     for (int i=1;i<=q;i++) if (op[i]==5) printf("%d\n",ans[i]);
141     return 0;
142 } 
时间: 2024-10-25 15:43:11

清橙A1484的相关文章

清橙A1363. 水位 - 清华大学2012年信息学优秀高中学子夏令营

问题描述 有一个正方形的地区,该地区特点鲜明:如果把它等分为N×N个小正方形格子的话,在每个格子内的任意地点的地表高度是相同的,并且是一个0到M之间的整数.正方形地区的外部被无限高的边界包围. 该地区可能会有积水.经过多年的观察,人们发现了几个关于积水的重要规律: 1. 每个格子要么完全没有积水,要么它内部的任意地点的水面高度都是相同的.并且水面高度一定大于地表高度. 2. 每个格子的水面高度在0~M之间,并且一定是整数. 3. 对于相邻(必须为边相邻)的两个格子,一定不会出现水自动从一个格子流

清橙A1212:剪枝

题面 清橙 Sol 一种新的树上\(DP\)姿势 从左往右按链\(DP\) 做法: 维护两个栈\(S1\),\(S2\) \(S1\)存当前的链 \(S2\)存分叉点以下要改的链 \(Dfs\),弄一个分叉点,之前的链经过它,并且另一条要转移到的链也经过它 那么每次在叶节点时就把\(S1\)最下面的一部分变成\(S2\) 转移 两种情况: 最大值在\(S1\)和在\(S2\)的情况 那么枚举\(S2\),\(S1\)中小于\(S2\)的枚举的值的点就可以转移,并维护\(S1\),\(S2\)的前

清橙A1206 小Z的袜子(莫队算法)

A1206. 小Z的袜子 时间限制:1.0s   内存限制:512.0MB 总提交次数:744   AC次数:210   平均分:44.44 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2010中国国家集训队命题答辩 问题描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是

[TS-A1505] [清橙2013中国国家集训队第二次作业] 树 [可持久化线段树,求树上路径第k大]

按Dfs序逐个插入点,建立可持久化线段树,每次查询即可,具体详见代码. 不知道为什么,代码慢的要死,, #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <vector> using

【清橙A1084】【FFT】快速傅里叶变换

问题描述 离散傅立叶变换在信号处理中扮演者重要的角色.利用傅立叶变换,可以实现信号在时域和频域之间的转换. 对于一个给定的长度为n=2m (m为整数) 的复数序列X0, X1, …, Xn-1,离散傅立叶变换将得到另一个长度为n的复数序列Y0, Y1, …, Yn-1.其中 Yi=X0+X1wi+ X2w2i+ X3w3i+…+ Xn-1w(n-1)i 其中w=e2πI/n=cos(2π/n)+I sin(2π/n),称为旋转因子,其中I为虚数单位,I2= –1. 给定输入序列X,请输出傅立叶变

清橙A1339. JZPLCM(顾昱洲)

http://www.tsinsen.com/ViewGProblem.page?gpid=A1339 题解:https://blog.csdn.net/LOI_DQS/article/details/51251737 对着题解A掉了...然而并不知道为什么要这么转化问题... 复杂度nlog^2n级别吧 1 #include<cstdio> 2 #include<algorithm> 3 #include<map> 4 #include<cmath> 5

【刷题】清橙 A1339 JZPLCM(顾昱洲)

试题来源 2012中国国家集训队命题答辩 问题描述 给定一长度为n的正整数序列a,有q次询问,每次询问一段区间内所有数的lcm(即最小公倍数).由于答案可能很大,输出答案模1000000007. 输入格式 第一行,两个整数,n, q,分别表示数列长度和询问个数. 下面n行,每行一个整数,第i行的整数为ai. 下面q行,每行两个整数l, r,表示询问下标i在[l, r]范围内的ai的lcm. 输出格式 q行.对于每个询问,输出一行,表示对应的答案. 样例输入 3 3 123 234 345 1 2

[tsA1490][2013中国国家集训队第二次作业]osu![概率dp+线段树+矩阵乘法]

这样的题解只能舔题解了,,,qaq 清橙资料里有.. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <ctime> 7 #include <algorithm> 8 9 using namespace std; 10 11 struct Mat

oj集

by http://www.cnblogs.com/yangqingli/p/4931360.html OnlineJudge大集合 什么是OJ Online Judge系统(简称OJ)是一个在线的判题系统.用户可以在线提交程序源代码,系统对源代码进行编译和执行,并通过预先设计的测试数据来检验程序源代码的正确性. 一个用户提交的程序在Online Judge系统下执行时将受到比较严格的限制,包括运行时间限制,内存使用限制和安全限制等.用户程序执行的结果将被Online Judge系统捕捉并保存,