nxt

树套树-线段树套平衡树

感情迁移 提交于 2019-11-28 08:56:37
树套树留坑 线段树套平衡树: 二逼平衡树 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> #include<map> #include<bitset> #pragma GCC optimize(2) #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define dwn(i,a,b) for(int i=(a);i>=(b);--i) using namespace std; typedef long long ll; const int N=6000000,inf=2147483647; int n,m,maxn,a[N+10]; int tot,rt[N+10],sz[N+10],rec[N+10],v[N+10],fa[N+10],ch[N+10][2]; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48);

Period

梦想与她 提交于 2019-11-28 08:41:11
这道题可以想到用KMP来解决,根据定义,对于每一个i,S[1-Nxt[i]+1~i]=S[1~Nxt[i]],并且不存在更大的循环节 Nxt[i]数组表示以i结尾的非前缀串与自身的前缀能匹配的最大数,可以方便更新 主要性质: 必要性:若循环元为len,当且仅S[1~i-len]=S[len+1~i] 充分性:从S[1~i-len]与S[len+1~i]各取len个字符,则S[1~len]=S[len+1~2*len],并以此类推,可以得出循环节的结论 Code #include<bits/stdc++.h> using namespace std; const int N=1e6+5; int nxt[N],n,cnt; char a[N]; inline void pre(){ nxt[1]=0; for(int i=2,j=0;i<=n;i++){ while(j>0&&a[i]!=a[j+1])j=nxt[j];//不断寻找能够继续匹配的 if(a[i]==a[j+1])++j;//继续更新 nxt[i]=j; } } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%s",&n, a+1); pre(); printf("Test case #%d\n",++cnt); for(int i=1;i<=n;i++

扩展KMP 洛谷P5410 模板

梦想的初衷 提交于 2019-11-28 04:13:49
题目链接: https://www.luogu.org/problem/P5410 题意:给两个字符串a,b,求b对a的每一个后缀的最大前缀长度 分析:扩展KMP(又称Z-algorithm算法)裸题 该博客讲解的比较好: https://www.luogu.org/blog/lc-2018-Canton/solution-p5410 但他有几个地方讲的有几个问题,主要在情况2里面 首先是一开始S[K+L]肯定是在p的后面,这个比较明显 然后情况二红蓝绿三条线的序列不是一样的,红绿还是一样的,但是蓝线就不等了,这个自己看一看 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+7;//单词间自行添加了符号,稍做扩大 const ll inf=1e18; #define meminf(a) memset(a,0x3f,sizeof(a)) #define mem0(a) memset(a,0,sizeof(a)); char a[maxn],b[maxn]; int nxt[maxn],extend[maxn];//nxt[i]代表b[i...len]和b的最大前缀长度,extend[i]代表a[i...len]和b的最大前缀长度 void getnxt(){

PAT A1105 Spiral Matrix [硬核模拟]

霸气de小男生 提交于 2019-11-28 01:27:44
题目描述 链接 将给定的N个正整数按非递增的顺序,填入“螺旋矩阵”~所谓“螺旋矩阵”,是指从左上角第1个格子开始,按顺时针螺旋方向填充~要求矩阵的规模为m行n列,满足条件:m*n等于N;m>=n;且m-n取所有可能值中的最小值 分析 方法1:就是按照题意模拟,我自己想到一个切换方向的方法,但是必须初始化的时候要注意! 方法2:while里面套while。内层while有4个,组成了一个整体,即走了一圈,外层while表示不断走圈,直到走完 一直最后一个样例错!!!!!一般都是大样例!!!检查下开的数组,发现没有指定范围!!! 此时!!!用vector!!! vector<int> a(N); //一维数组 vector<vector<int> > b(m, vector<int>(n)); //二维数组!!!有m行,每行是一个n列的一维数组! 二维数组初始化 memset(a, -1,sizeof(a)); //一样的 代码1 #include<bits/stdc++.h> using namespace std; const int maxn = 1000; int a[maxn][maxn]; bool v[maxn][maxn]; const int maxm = 1e4+10; int b[maxm]; int t,m,n; int main(){ cin>>t; for

@codeforces - 117C@ Cycle

喜夏-厌秋 提交于 2019-11-28 00:04:34
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个竞赛图(有向完全图),请找出里面的某个三元环,或者判断不存在这样的环。 Input 第一行包含一个整数 n (1 ≤ n ≤ 5000)。 接下来 n 行包含这个图的邻接矩阵,其中 A[i, j] = 1 表示存在一条 i 到 j 的边。 保证 A[i, i] = 0, A[i, j] ≠ A[j, i] (1 ≤ i, j ≤ n, i ≠ j)。 Output 如果无解,输出 -1;否则输出三个不同的顶点 a1, a2, a3 使得 A[a1, a2] = 1, A[a2, a3] = 1, A[a3, a1] = 1。 任意解即可。 Examples Input 5 00100 10000 01001 11101 11000 Output 1 3 2 Input 5 01111 00000 01000 01100 01110 Output -1 @solution@ 根据竞赛图的性质,如果有环,则一定存在三元环。证明可以通过一个 n 元环一步步缩成一个三元环。 那么假如前 i 个点没有三元环,则一定构成 DAG,考虑维护前 i 个点的拓扑序 p[1...i]。 考虑加入第 i + 1 个点,如果依然无法构成环,则存在一个 j 使得 p

图上求最小环

徘徊边缘 提交于 2019-11-27 22:21:00
最近做了道 水题 题,信息传递,题目要求就是求出有向图的最小环。 做完乍一看题解有好多好多种办法,在此整理一下。 我对于这道题的做法是: 由于每个点最多连出一条边,所以可能存在两个环相连的情况,所以对于入度为0的点删掉就好,然后不断删不断删, 直到删到图上仅有环,就一个一个求一求环的大小,取最小的那一个。 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 200005 6 7 using namespace std; 8 9 int nxt[maxn],ans=2147483647,ind[maxn],n; 10 bool vis[maxn]; 11 12 inline void cancel(int k) 13 { 14 int e=nxt[k]; 15 ind[k]=0; ind[nxt[k]]--; nxt[k]=-1; 16 if(ind[e]==0) cancel(e); 17 } 18 19 inline void dfs(int x_now,int st,int len) 20 { 21 if(x_now==st&&len!=0) 22 { 23 vis[x_now]=true; 24 ans=min(ans,len); 25

Bzoj3786: 星系探索——Splay

纵饮孤独 提交于 2019-11-27 14:08:05
题面    Bzoj3786 解析    上课讲稿上的例题   这道题是套路题,是括号序的应用,进入节点时打上$+1$标记, 退出时打上$-1$标记,这个是作为点权的系数   先看操作2, 需要更改父节点,就是把一段区间提取出来,插入另一个地方,显然可以用Splay维护,先提取区间,再把新父亲的$+1$点旋转至根,把区间挂在根的后继的左儿子上,再把这个节点旋转至根,以更新信息   对于操作1,求点到根的路径和,就是求括号序列的前缀和,该点对应的$+1$点或$-1$点的前缀和都可,我是把$-1$的点旋转至根,答案就是根的左儿子的子树和,因此需要维护子树和   最后还有操作3,显然打标记,问题在对于子树和的改变, 记该子树中$+1$标记有$cnt1$个,$-1$标记有$cnt_1$个,则子树和需要加$(cnt1 - cnt_1) * delta$,因此需要维护子树中$+1$与$-1$的个数   代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn = 100004; template<class T> void read(T &re) {

Period

杀马特。学长 韩版系。学妹 提交于 2019-11-27 13:47:29
For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A K ,that is A concatenated K times, for some string A. Of course, we also want to know the period K. Input The input consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S.The second line

2019-8-15 考试总结

我是研究僧i 提交于 2019-11-27 10:58:51
A. 数论 数学题,经实践证明,这个题可以$AC$。 考试时打的暴力,拿到$20$分。 正解: 虽然现在思路还是有点模糊,但是大体的思路应该差不多。 首先,就像题解说的,如果对于一个非良好数$x$,$xp^c$也是非良好数,其中$p$为质数,$c>=0$。 前提是$x$中不含质因子$p$。 $xp^c$的约数个数$val[xp^c]$是$val[x]\times (c-1)$。 $x$中没有质因子$p$,当然他的约数中也没有质因子$p$,所以每次乘$p$都会形成新的约数。 之后就是一些玄学的操作。 每次" 迭代 "$($新名词$)$,把原序列中的数拓展, 先枚举素数,再枚举原序列中的数,再枚举指数,把新数存到临时的数组中。 最后删去新的临时数组中不合法的数,因为这个数不会再更新别的数了。 注意要排序。 再维护一个堆,维护前$k+1$大的约数个数。 这样就可以删掉当前不合法的数了,应该是当前,因为之后插进来的数还可能再使它不合法。 最后一定可以筛掉所有不合法的数。 最后$TLE70$。 丑陋的代码: #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<queue> #define _min(x,y) ((x)<(y)?(x):(y)) #define _max(x,y)

CodeForces 1200E Compress Words

℡╲_俬逩灬. 提交于 2019-11-27 09:58:07
\(C_n^m\) 的typora,点了一下 启用源代码模式 就把我已经写好的博客弄没了,就给我留个标题,自动保存也只给我保存了个标题…… \(C_n^m\) ,wdnmd Time limit 1000 ms Memory limit 262144 kB 解题思路 KMP 打比赛的时候愣是想不到怎么用KMP,总想着如果用kmp,那么每次合并都要更新nxt数组,会被卡到n方,就是想不到老字符串不用每次都全体参与KMP,每次只需要把老字符串后面那段拿出来判断就行了……还想着是不是要用啥我现在还不会的高级玩意……对KMP的理解只停留在做最裸的那种板题…… KMP有两种玩法,目的都是在合并老字符串(之前合并的结果)和新字符串(最新读入的)的时候找出可以被合并的长度,然后就能把新字符串后面那截不能合并的接到老字符串后面。 边写边骂typora 。由于合并的时候,老字符串和新字符串重复的长度小于等于新字符串的长度,所以处理的时候都截取老字符串后面和新字符串等长的一截(如果新字符串比老字符串长,那么就选整个老字符串) 一种是 官方题解 的思路——先把新字符串放前面,把“老字符串的后面一截”放后面,然后对于这个新接的合体字符串跑一遍KMP,求出nxt数组,以便找到最长的border(这个是nxt数组的定义了),这个就是可以合并的长度了