fa

奇偶游戏

荒凉一梦 提交于 2019-11-27 04:43:05
题目链接 题意:有一个01串S,长度为n,一个人说出k个关于01串的回答,描述S[l~r] 中有奇数个1还是偶数个1。依次看,判断他到第几个问题都是可靠的回答。 思路:首先n很大要离散化,然后因为很容易想到如果S[l,r]为奇数,则S[1,r]为偶数,S[1,l-1]为奇数,或者S[1,r]为奇数,S[1,l-1]为偶数。如果S[l,r]为偶数,则 那两个区间奇偶性相同。所以可以用扩展域,扩展每个[1,x]的奇数和偶数两种情况,然后并查集。 #include<cstring> #include<algorithm> #include<vector> #include<map> #include<queue> #include<cstdio> #include<cmath> #define ll long long using namespace std; struct point { int l; int r; int ans; }query[10010]; int a[20010],fa[20010],n,m,t; void read_discrete() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { char str[5]; scanf("%d%d%s",&query[i].l,&query[i].r,str); query[i]

POJ 1611---The Suspects(并查集)

感情迁移 提交于 2019-11-26 19:09:43
题意:0疑似有传染病,和0在一起的都疑似被传染(这些人也会传染别人),求有多少个人可能有传染病; 直接代码+注释 (16ms) 1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 6 const int maxn=20000000; 7 int par[maxn],m,n; 8 9 int find(int x) 10 { 11 if(x!=par[x]) 12 par[x]=find(par[x]); 13 return par[x]; 14 } 15 16 void unionn(int a,int b) 17 { 18 int fa=find(a); 19 int fb=find(b); 20 if(par[fb]!=fb) par[fa]=fb; //如果fb不是头 fa并入fb即头为fb 21 else par[fb]=fa; //如果fb是头 fb并入fa 22 } 23 24 int main() 25 { 26 while(scanf("%d%d",&n,&m)&&(m||n)){ 27 int p,a,b; 28 for(int i=0;i<=n;i++){ 29 par[i]=i; //每个人的头为自己 30 } 31 while(m--)

后缀自动机

爱⌒轻易说出口 提交于 2019-11-26 17:00:02
后缀自动机是一个很复杂的算法,下面讲一讲建图和应用。 建图 首先要明确后缀自动机上点和含义:一个点代表的是一类有相同后缀的字符串,而每一个点的fail一定是它本身的后缀。 那么我们定义如下结构体: struct point { int len; int fa; int ch[30]; }; point a[MAXN]; 其中fa就是fail,ch表示点的出边(a~z),len就表示这个点能表示的最大后缀长度。 然后对于一个字符串,我们每次加入一个点。 设当前点为np,之前的主干上的最后一个点为p,当前加入的字符为c。 显然,a[np].len=a[p].len+1(因为从a[p].len出来加上一个c字符就到了np)。 接着我们就要求fail,这一个要分类讨论。 我们从np开始跳fail链,要保证跳到的点的没有c出边,对于这些点,我们把它的c出边设为np。 然后如果直接跳到了1都还没有发现一个有c出边的点,那么就把a[np].fail设为1(这个是case1)。 如果找到了一个有c出边的点,设它的出边连向q,那么就判断一下a[q].len==a[p].len+1(注意此时p是那个有c出边的点)。 如果相等,那么a[np].fa=q,这一个是没问题的了(case2)。 否则我们还要新建一个nq,使a[nq].len=a[p].len+1,然后把q的出边信息全部赋给nq。接下来,a