lct [NOI2014]魔法森林
#include <bits/stdc++.h> using namespace std; const int N=2e5; int v[N],data[N],data2[N],leftson[N],rightson[N],fa[N],n,m; bool rev[N]; struct re { int a,b,c,d; }a[N*2]; void updata(int x) { data[x]=max(v[x],max(data[leftson[x]],data[rightson[x]])); if (data[x]==v[x]) data2[x]=x; if (data[x]==data[leftson[x]]) data2[x]=data2[leftson[x]]; if (data[x]==data[rightson[x]]) data2[x]=data2[rightson[x]]; } void down(int x) { if (!rev[x]) return; swap(leftson[x],rightson[x]); rev[leftson[x]]^=1; rev[rightson[x]]^=1; rev[x]=0; } bool pd(int x) { if (leftson[fa[x]]!=x&&rightson[fa[x]]!=x) return(0); else return(1); } void rotate(int x,int y) { int father=fa[x]; if (y==1) { rightson[father]=leftson[x]; if (leftson[x]) fa[leftson[x]]=father; } else { leftson[father]=rightson[x]; if (rightson[x]) fa[rightson[x]]=father; } fa[x]=fa[father]; if (pd(father)) { if (leftson[fa[x]]==father) leftson[fa[x]]=x; else rightson[fa[x]]=x; } if (y==1) leftson[x]=father; else rightson[x]=father; fa[father]=x; updata(father); updata(x); } void dfs(int x) { if (pd(x)) dfs(fa[x]); down(x); } void splay(int x) { dfs(x); int father=fa[x]; while (pd(x)) { if (!pd(father)) { if (leftson[father]==x) rotate(x,2); else rotate(x,1); } else { if (leftson[fa[father]]==father) if (leftson[father]==x) rotate(father,2),rotate(x,2); else rotate(x,1),rotate(x,2); else if (rightson[father]==x) rotate(father,1),rotate(x,1); else rotate(x,2),rotate(x,1); } father=fa[x]; } } void access(int x) { for (int y=0;x;y=x,x=fa[x]) splay(x),rightson[x]=y,updata(x); } void makeroot(int x) { access(x); splay(x); rev[x]^=1; } int findroot(int x) { access(x); splay(x); while (leftson[x]) x=leftson[x]; return x; } void split(int x,int y) { makeroot(x); access(y); splay(y); } void cut(int x,int y) { makeroot(x); if (findroot(y)==x&&fa[x]==y&&!rightson[x]) fa[x]=leftson[y]=0; } void link(int x,int y) { makeroot(x); if (findroot(y)!=x) fa[x]=y; } bool cmp(re x,re y) { return(x.c<y.c); } bool find(int x,int y) { makeroot(x); if (findroot(y)==x) return(1); else return(0); } int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); cin>>n>>m; for (int i=1;i<=m;i++) cin>>a[i].a>>a[i].b>>a[i].c>>a[i].d; sort(a+1,a+m+1,cmp); int ans=1e9; for (int i=1;i<=m;i++) { int x=a[i].a,y=a[i].b; if (find(x,y)) { split(x,y); if (data[y]>a[i].d) { int p=data2[y]; cut(p,a[p-n].a); cut(p,a[p-n].b); v[i+n]=a[i].d; link(i+n,x); link(i+n,y); } } else { v[i+n]=a[i].d; link(i+n,x); link(i+n,y); } if (find(1,n)) { split(1,n); ans=min(ans,a[i].c+data[n]); } } if (ans==1e9) cout<<-1; else cout<<ans; }
AC自动机 hdu 2825
#include <bits/stdc++.h> using namespace std; #define mo 20090717 int dy[2000],cnt,dp[27][250][1050],w[2000],ff[500][27],fail[500]; int n,m,kk; char c[1000009]; void insert(char *s,int x) { int now=0; for (int i=0;i<strlen(s);i++) if (ff[now][s[i]-'a']) now=ff[now][s[i]-'a']; else ff[now][s[i]-'a']=++cnt,now=cnt; w[now]|=1<<(x-1); } queue<int> q; void build() { for (int i=0;i<26;i++) if (ff[0][i]) q.push(ff[0][i]); while (!q.empty()) { int x=q.front(); q.pop(); for (int i=0;i<26;i++) { if (ff[x][i]) { fail[ff[x][i]]=ff[fail[x]][i]; q.push(ff[x][i]); } else ff[x][i]=ff[fail[x]][i]; w[ff[x][i]]|=w[ff[fail[x]][i]]; } } } int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); for (int i=1;i<=1028;i++) { int l=0; for (int j=0;j<=10;j++) if ((i>>j)%2==1) l++; dy[i]=l; } while (cin>>n>>m>>kk&&n) { memset(ff,0,sizeof(ff)); memset(w,0,sizeof(w)); memset(dp,0,sizeof(dp)); memset(fail,0,sizeof(fail)); for (int i=1;i<=m;i++) { cin>>c; insert(c,i); } build(); dp[0][0][0]=1; for (int i=0;i<n;i++) for (int j=0;j<=cnt;j++) for (int k=0;k<=(1<<m)-1;k++) if (dp[i][j][k]) for (int u=0;u<26;u++) { int v=ff[j][u]; dp[i+1][v][k|w[v]]+=dp[i][j][k]; dp[i+1][v][k|w[v]]%=mo; } int ans=0; for (int k=0;k<=(1<<m)-1;k++) if (dy[k]>=kk) for (int j=0;j<=cnt;j++) ans+=dp[n][j][k],ans%=mo; cout<<ans<<endl; } return 0; }
kmp 写矩阵的时候总会犯一些zz错误。。比如没有返回值,行列搞反
[HNOI2008]GT考试
#include <bits/stdc++.h> using namespace std; int n,m,mo1,fail[100]; char c[100]; struct re{ int jz[30][30]; }a; void get_fail() { for (int i=1;i<strlen(c);i++) { int x=fail[i]; while (x&&c[i]!=c[x]) x=fail[x]; fail[i+1]=c[i]==c[x]?x+1:0; } } int find(int x,char cc) { while (x&&c[x]!=cc) x=fail[x]; if (c[x]==cc) x++; return(x); } re XX(re x,re y) { re tmp; memset(tmp.jz,0,sizeof(tmp.jz)); int len=strlen(c); for (int i=1;i<=len;i++) for (int j=1;j<=len;j++) for (int k=1;k<=len;k++) tmp.jz[i][k]+=x.jz[i][j]*y.jz[j][k], tmp.jz[i][k]%=mo1; return(tmp); } re fast_pow(int x) { if (x==1) return(a); re b=fast_pow(x/2); b=XX(b,b); if (x%2==1) b=XX(b,a); return b; } int main() { freopen("noip.in","r",stdin); freopen("noip.out","w",stdout); std::ios::sync_with_stdio(false); cin>>n>>m>>mo1; cin>>c; get_fail(); for (int i=0;i<strlen(c);i++) for (int j=0;j<10;j++) if (find(i,j+'0')!=strlen(c)) a.jz[find(i,j+'0')+1][i+1]++, a.jz[find(i,j+'0')+1][i+1]%=mo1; re d=fast_pow(n); int ans=0; for (int i=0;i<strlen(c);i++) ans+=d.jz[i+1][1],ans%=mo1; cout<<ans; return 0; }
矩阵优化 循环矩阵乘起来还是循环矩阵
树链剖分
平衡树
线段树
序列记树