LCA
//exam:P3379 【模板】最近公共祖先(LCA)
#include <iostream>
#include <cstdio>
#include <vector>
#define int long long
using namespace std;
const int MAXN=5e5+5,MAXM=25;
void dfs(int,int);
int lca(int,int);
vector<int> g[MAXN];
int deep[MAXN];
int n,q,s;
signed main(){
cin>>n>>q>>s;
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(s,0);
while(q--){
int a,b;
cin>>a>>b;
cout<<lca(a,b)<<endl;
}
return 0;
}
int f[MAXN][MAXM];
void dfs(int u,int fa){
f[u][0]=fa,deep[u]=deep[fa]+1;
for(int i=1;i<=20;i++){
f[u][i]=f[f[u][i-1]][i-1];
}
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(v!=fa){
dfs(v,u);
}
}
}
int lca(int u,int v){
if(deep[u]<deep[v]){
swap(u,v);
}
int l=deep[u]-deep[v];
for(int i=0;i<=20;i++){
if(l&(1<<i)){
u=f[u][i];
}
}
if(u==v){
return u;
}
for(int i=20;i>=0;i--){
if(f[u][i]!=f[v][i]){
u=f[u][i],v=f[v][i];
}
}
return f[u][0];
}
树状数组
//exam:T588519 树状数组 3 :区间修改,区间查询
#include <iostream>
#include <cstdio>
#define int long long
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int MAXN=1e6+5;
int query(int x);
void update(int x,int v);
int tree1[MAXN],tree2[MAXN];
int n,q;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=1,u;i<=n;i++){
cin>>u;
update(i,u);
update(i+1,-u);
}
while(q--){
int op,l,r,x;
cin>>op>>l>>r;
if(op==1){
cin>>x;
update(l,x);
update(r+1,-x);
}else{
cout<<query(r)-query(l-1)<<endl;
}
}
return 0;
}
int query(int x){
int res=0,res1=0,t=x;
while(x){
res+=tree1[x];
res1+=tree2[x];
x-=lowbit(x);
}
return res*(t+1)-res1;
}
void update(int x,int v){
int v1=x*v;
while(x<=n){
tree1[x]+=v;
tree2[x]+=v1;
x+=lowbit(x);
}
}
线段树
加法
//exam:P3372 【模板】线段树 1
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
const int MAXN=1e5+5;
void build(int,int,int);
int query(int,int,int);
void update(int,int,int,int);
int a[MAXN];
int n,m;
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=1,op,x,y,k;i<=m;i++){
cin>>op>>x>>y;
if(op==1){
cin>>k;
update(1,x,y,k);
} else{
cout<<query(1,x,y)<<endl;
}
// for(int i=1;i<=n;i++){
// cout<<query(1,i,i)<<" ";
// }
// cout<<endl;
}
return 0;
}
struct SegmentTree{
int value,l,r,add;
#define value(x) tree[x].value//节点权值
#define l(x) tree[x].l
#define r(x) tree[x].r
#define add(x) tree[x].add
#define ltree(x) ((x)<<1)
#define rtree(x) (((x)<<1)+1)
#define treesize(x) (r(x)-l(x)+1)
#define mid(x) ((l(x)+r(x))>>1)
}tree[MAXN*4];
void build(int root,int l,int r){
l(root)=l,r(root)=r;
if(l==r){
value(root)=a[l];
return ;
}
int mid=mid(root);
build(ltree(root),l,mid);
build(rtree(root),mid+1,r);
value(root)=value(ltree(root))+value(rtree(root));
return ;
}
void spread(int x){
value(ltree(x))+=add(x)*treesize(ltree(x));
value(rtree(x))+=add(x)*treesize(rtree(x));
add(ltree(x))+=add(x);
add(rtree(x))+=add(x);
add(x)=0;
}
int query(int root,int l,int r){
if(l<=l(root)&&r(root)<=r){
return value(root);
}
spread(root);
int mid=mid(root),res=0;
if(mid>=l){
res+=query(ltree(root),l,r);
}if(mid<r){
res+=query(rtree(root),l,r);
}
return res;
}
void update(int root,int l,int r,int x){
if(l<=l(root)&&r(root)<=r){
add(root)+=x;
value(root)+=x*treesize(root);
return ;
}
spread(root);
int mid=mid(root);
if(mid>=l){
update(ltree(root),l,r,x);
}if(mid<r){
update(rtree(root),l,r,x);
}
value(root)=value(ltree(root))+value(rtree(root));
}
加法和乘法
//exam:P3373 【模板】线段树 2
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
const int MAXN=1e5+5;
void build(int,int,int);
int query(int,int,int);
void update1(int,int,int,int);
void update2(int,int,int,int);
int a[MAXN];
int n,m,P;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m>>P;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=1,op,x,y,k;i<=m;i++){
cin>>op>>x>>y;
if(op==1){
cin>>k;
update2(1,x,y,k);
} else if(op==2){
cin>>k;
update1(1,x,y,k);
} else{
cout<<query(1,x,y)<<endl;
}
// cout<<"#";
// for(int i=1;i<=n;i++){
// cout<<query(1,i,i)<<" ";
// }
// cout<<endl;
}
return 0;
}
struct SegmentTree{
int value,l,r,add,mul;
#define value(x) tree[x].value//节点权值
#define l(x) tree[x].l
#define r(x) tree[x].r
#define add(x) tree[x].add
#define mul(x) tree[x].mul
#define ltree(x) ((x)<<1)
#define rtree(x) (((x)<<1)+1)
#define treesize(x) (r(x)-l(x)+1)
#define mid(x) ((l(x)+r(x))>>1)
}tree[MAXN*4];
void build(int root,int l,int r){
l(root)=l,r(root)=r,mul(root)=1;
if(l==r){
value(root)=a[l];
return ;
}
int mid=mid(root);
build(ltree(root),l,mid);
build(rtree(root),mid+1,r);
value(root)=value(ltree(root))+value(rtree(root));
return ;
}
void spread(int x){
value(ltree(x))=value(ltree(x))*mul(x)%P;
value(rtree(x))=value(rtree(x))*mul(x)%P;
value(ltree(x))=(value(ltree(x))+add(x)*treesize(ltree(x))%P)%P;
value(rtree(x))=(value(rtree(x))+add(x)*treesize(rtree(x))%P)%P;
add(ltree(x))=(add(ltree(x))*mul(x)%P+add(x))%P;
add(rtree(x))=(add(rtree(x))*mul(x)%P+add(x))%P;
mul(ltree(x))=mul(ltree(x))*mul(x)%P;
mul(rtree(x))=mul(rtree(x))*mul(x)%P;
add(x)=0,mul(x)=1;
}
int query(int root,int l,int r){
if(l<=l(root)&&r(root)<=r){
return value(root);
}
spread(root);
int mid=mid(root),res=0;
if(mid>=l){
res=(res+query(ltree(root),l,r))%P;
}if(mid<r){
res=(res+query(rtree(root),l,r))%P;
}
return res;
}
void update1(int root,int l,int r,int x){
if(l<=l(root)&&r(root)<=r){
add(root)=(add(root)+x)%P;
value(root)=(value(root)+x*treesize(root)%P)%P;
return ;
}
spread(root);
int mid=mid(root);
if(mid>=l){
update1(ltree(root),l,r,x);
}if(mid<r){
update1(rtree(root),l,r,x);
}
value(root)=(value(ltree(root))+value(rtree(root)))%P;
}
void update2(int root,int l,int r,int x){
if(l<=l(root)&&r(root)<=r){
add(root)=add(root)*x%P;
mul(root)=mul(root)*x%P;
value(root)=(value(root)*x%P)%P;
return ;
}
spread(root);
int mid=mid(root);
if(mid>=l){
update2(ltree(root),l,r,x);
}if(mid<r){
update2(rtree(root),l,r,x);
}
value(root)=(value(ltree(root))+value(rtree(root)))%P;
}
分块
//exam:243. 分块
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#define int long long
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=5e5+5;
void init();
int query(int,int,int);
void update(int,int,int);
pair<int,int> a[MAXN];
int n,m;
int T;
signed main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
int t;
cin>>t;
a[i]=make_pair(t,i);
}
init();
for(int i=1;i<=n;i++){
int op,l,r,x;
cin>>op>>l>>r>>x;
if(op==1){
cout<<query(l,r,x*x)<<endl;
}else{
update(l,r,x);
}
}
return 0;
}
int pos[MAXN],L[MAXN],R[MAXN],add[MAXN];
void init(){
T=sqrt(n);
for(int i=1;i<=T;i++){
L[i]=(i-1)*T+1,R[i]=i*T;
}
if(R[T]<n){
L[T+1]=R[T]+1,R[T+1]=n;
T++;
}
for(int i=1;i<=T;i++){
sort(a+L[i],a+1+R[i]);
for(int j=L[i];j<=R[i];j++){
pos[j]=i;
}
}
}
int query(int x,int y,int k){
int l=pos[x],r=pos[y],ans=0;
if(l==r){
for(int i=L[l];i<=R[l];i++){
if(a[i].second>=x&&a[i].second<=y&&a[i].first<k-add[l]){
ans++;
}
}
}else{
for(int i=L[l];i<=R[l];i++){
if(a[i].second>=x&&a[i].first<k-add[l]){
ans++;
}
}
for(int i=l+1;i<=r-1;i++){
ans+=lower_bound(a+L[i],a+R[i]+1,make_pair(k-add[i],-INF))-a-L[i];
}
for(int i=L[r];i<=R[r];i++){
if(a[i].second<=y&&a[i].first<k-add[r]){
ans++;
}
}
}
return ans;
}
void update(int x,int y,int k){
int l=pos[x],r=pos[y];
if(l==r){
for(int i=L[l];i<=R[l];i++){
if(a[i].second>=x&&a[i].second<=y){
a[i].first+=k;
}
}
sort(a+L[l],a+R[l]+1);
}else{
for(int i=L[l];i<=R[l];i++){
if(a[i].second>=x){
a[i].first+=k;
}
}
sort(a+L[l],a+R[l]+1);
for(int i=l+1;i<=r-1;i++){
add[i]+=k;
}
for(int i=L[r];i<=R[r];i++){
if(a[i].second<=y){
a[i].first+=k;
}
}
sort(a+L[r],a+R[r]+1);
}
}
A*算法
//exam:P2901 [USACO08MAR] Cow Jogging G
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define int long long
using namespace std;
struct node{
int next,w;
bool operator < (const node &nxt) const{
if(w!=nxt.w){
return w>nxt.w;
}
return next>nxt.next;
}
};
const int MAXN=1005;
void build();//建立估算数组
void output();
vector<node> g[MAXN],g0[MAXN];
priority_queue<node> q;
int d[MAXN];//估算数组
int n,m,k;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m>>k;
for(int i=1,u,v,w;i<=m;i++){
cin>>u>>v>>w;
g[u].push_back((node){v,w});
g0[v].push_back((node){u,w});
}
build();
q.push((node){n,d[n]});
while(!q.empty()){
node u=q.top();q.pop();
// cout<<u.next<<" "<<u.w-d[u.next]<<" "<<u.w<<endl;
if(u.next==1){
cout<<u.w<<endl;
k--;
if(k==0){
break;
}
}
for(int i=0;i<g[u.next].size();i++){
node v=g[u.next][i];
q.push((node){v.next,d[v.next]+u.w-d[u.next]+v.w});
}
}
while(k){
cout<<-1<<endl;
k--;
}
return 0;
}
void add(int v,int w){
if(d[v]>=w){
d[v]=w;
q.push((node){v,w});
}
}
void build(){
for(int i=1;i<=n;i++){
d[i]=0x3f3f3f3f;
}
add(1,0);
while(!q.empty()){
node u=q.top();q.pop();
if(d[u.next]<u.w){
continue;
}
for(int i=0;i<g0[u.next].size();i++){
node v=g0[u.next][i];
add(v.next,u.w+v.w);
}
}
}
最小生成树
//exam:P3366 【模板】最小生成树
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#define int long long
using namespace std;
struct node{
int v,w;
};
struct edge{
int u,v,w;
bool operator < (const edge &nxt) const{
return w>nxt.w;
}
};
const int MAXN=5e3+5;
int solve();
bool check();
priority_queue<edge> q;
vector<node> g[MAXN],a[MAXN];
int n,m,ans;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1,u,v,w;i<=m;i++){
cin>>u>>v>>w;
g[u].push_back((node){v,w});
g[v].push_back((node){u,w});
q.push((edge){u,v,w});
}
ans=solve();
if(!check()){
cout<<"orz";
}else{
cout<<ans;
}
return 0;
}
bool book[MAXN];
void dfs(int cur){
book[cur]=true;
for(int i=0;i<a[cur].size();i++){
node u=a[cur][i];
if(!book[u.v]){
dfs(u.v);
}
}
}
bool check(){
dfs(1);
for(int i=1;i<=n;i++){
if(!book[i]){
return false;
}
}
return true;
}
int fa[MAXN];
void init(){
for(int i=1;i<=n;i++){
fa[i]=i;
}
}
int find(int x){
if(fa[x]==x){
return x;
}
return fa[x]=find(fa[x]);
}
void unity(int x,int y){
int a=find(x),b=find(y);
if(a==b){
return ;
}
fa[a]=b;
}
bool same(int x,int y){
return find(x)==find(y);
}
int solve(){
init();
int ans=0;
while(!q.empty()){
edge u=q.top();q.pop();
if(same(u.u,u.v)){
continue;
}
unity(u.u,u.v);
a[u.u].push_back((node){u.v,u.w});
a[u.v].push_back((node){u.u,u.w});
ans+=u.w;
}
return ans;
}
埃氏筛
//exam:P3383 【模板】线性筛素数
#include <iostream>
#include <cstdio>
#include <cmath>
//#define int long long
using namespace std;
const int MAXN=2e8+5;
bool book[MAXN];
int a[MAXN],b[MAXN];
int n,q,m;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=2;i<=n;i++){
if(!book[i]){
b[++m]=i;
for(int j=i*2;j<=n;j+=i){
book[j]=true;
}
}
}
for(int i=1;i<=q;i++){
int x;
cin>>x;
cout<<b[x]<<endl;
}
return 0;
}
线性筛
//exam:P3383 【模板】线性筛素数(线性筛)
#include <iostream>
#include <cstdio>
#include <cmath>
//#define int long long
using namespace std;
const int MAXN=2e8+5;
bool book[MAXN];
int a[MAXN],b[MAXN];
int n,q,m;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=2;i<=n;i++){
if(!book[i]){
b[++m]=i;
}
for(int j=1;j<=m&&i*b[j]<=n;j++){
book[i*b[j]]=true;
if(i%b[j]==0){
break;
}
}
}
for(int i=1;i<=q;i++){
int x;
cin>>x;
cout<<b[x]<<endl;
}
return 0;
}
扩展欧几里得定理
//exam:P1082 [NOIP 2012 提高组] 同余方程
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
void exgcd(int a,int b,int &x,int &y);
int a,b,x,y;
signed main(){
ios::sync_with_stdio(false);
cin>>a>>b;
exgcd(a,b,x,y);
cout<<x<<" "<<y;
return 0;
}
void exgcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;
return ;
}
exgcd(b,a%b,x,y);
int x1=x,y1=y;
x=y1,y=(x1-a/b*y1);
}
费马小定理&错排计数
//exam:P4071 [SDOI2016] 排列计数
#include <iostream>
#include <cstdio>
#define int long long
#define endl '\n'
using namespace std;
const int P=1e9+7;
const int MAXN=1e6+5;
void build();
int solve(int,int);
int t,n,m;
signed main(){
ios::sync_with_stdio(false);
build();
cin>>t;
while(t--){
cin>>n>>m;
cout<<solve(n,m)<<endl;
}
return 0;
}
int f[MAXN],finv[MAXN],dp[MAXN];
int qpow(int x,int y){
int res=1;
while(y){
if((y&1)==1){
res=res*x%P;
}
y>>=1;
x=x*x%P;
}
return res;
}
void build(){
f[0]=finv[0]=1,dp[2]=1,dp[0]=1;
for(int i=1;i<=1e6;i++){
finv[i]=finv[i-1]*qpow(i,P-2)%P;//阶乘逆元
f[i]=f[i-1]*i%P;
if(i>=3){
dp[i]=(i-1)*(dp[i-1]+dp[i-2])%P;
}
}
}
int C(int n,int m){
return f[n]*finv[m]%P*finv[n-m]%P;
}
int solve(int n,int m){
return C(n,m)*dp[n-m]%P;
}
字符串哈希
//exam:P10468 兔子与兔子
#include <iostream>
#include <cstdio>
#define int unsigned long long
using namespace std;
const int MAXN=1e6+5;
const int P=1331;
int hs(int,int);
string s;
int H[MAXN],PS[MAXN];
int n,x1,x2,y1,y2;
signed main(){
ios::sync_with_stdio(false);
cin>>s>>n;s=" "+s;
PS[0]=1;
for(int i=1;i<s.size();i++){
H[i]=H[i-1]*P+s[i];
PS[i]=PS[i-1]*P;
}
while(n--){
cin>>x1>>y1>>x2>>y2;
int h1=hs(x1,y1),h2=hs(x2,y2);
if(h1==h2){
cout<<"Yes\n";
}else{
cout<<"No\n";
}
}
return 0;
}
int hs(int l,int r){
return H[r]-H[l-1]*PS[r-l+1];
}
Trie
//exam:P10470 前缀统计
#include <iostream>
#include <cstring>
#include <cstdio>
#define int long long
#define endl '\n'
using namespace std;
const int MAXN=1e6+5;
const int MAXM=30;
struct trie{
#define idx(c) ((c)-'a')
int ch[MAXN][MAXM];//ch[i][j]表示节点,j表示边
int val[MAXN];//记录当前节点的信息
int size;//节点数量
trie(){//构造函数
size=0;
memset(ch[0],0,sizeof(ch[0]));
}
void insert(string s){
int u=0;
for(int i=0;i<s.size();i++){
int t=idx(s[i]);
if(ch[u][t]==0){
size++;
memset(ch[size],0,sizeof(ch[size]));
ch[u][t]=size;
}
u=ch[u][t];
}
val[u]++;
}
int query(string s){
int u=0,res=val[0];
for(int i=0;i<s.size();i++){
int t=idx(s[i]);
if(ch[u][t]==0){
break;
}
u=ch[u][t];
res+=val[u];
}
return res;
}
};
int n,m;
trie t;
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++){
string s;
cin>>s;
t.insert(s);
}
for(int i=1;i<=m;i++){
string s;
cin>>s;
cout<<t.query(s)<<endl;
}
return 0;
}
KMP
//exam:P3375 【模板】KMP
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
const int MAXN=1e6+5;
void getF(string);
int fail[MAXN];//失配
string s1,s2;
int cur;
signed main(){
ios::sync_with_stdio(false);
cin>>s2>>s1;//模式串,匹配串
getF(s1);
for(int i=0;i<s2.size();i++){
if(s1[cur]==s2[i]){
cur++;
}else{
while(cur&&s2[i]!=s1[cur]){
cur=fail[cur];
}
cur=(s2[i]==s1[cur]?(cur+1):0);
}
if(cur==s1.size()){
cout<<i-s1.size()+2<<endl;
cur=fail[cur];
}
}
for(int i=1;i<=s1.size();i++){
cout<<fail[i]<<" ";
}
return 0;
}
void getF(string s){
fail[0]=fail[1]=0;
int l=s.size();
for(int i=1;i<l;i++){//从i状态算i+1
int cur=fail[i];//失配之后到达的状态
while(cur&&s[cur]!=s[i]){//不断失配
cur=fail[cur];
}
fail[i+1]=(s[cur]==s[i]?(cur+1):0);
}
}
Tarjan
割点
//exam name: P3388 【模板】割点(割顶)
#include <iostream>
#include <cstdio>
#include <vector>
#define int long long
using namespace std;
const int MAXN=2e4+5;
bool check(int);
void tarjan(int,int);
vector<int> g[MAXN];
bool book[MAXN];
int n,m,res;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1,u,v;i<=m;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=n;i++){
if(!check(i)){
tarjan(i,i);
}
}
for(int i=1;i<=n;i++){
res+=book[i];
}
cout<<res<<endl;
for(int i=1;i<=n;i++){
if(book[i]){
cout<<i<<" ";
}
}
return 0;
}
int dfn[MAXN],low[MAXN];
int dfncnt;
bool check(int u){
return dfn[u];
}
void tarjan(int u,int root){
low[u]=dfn[u]=++dfncnt;
int size=0;
for(auto v:g[u]){
if(!dfn[v]){
tarjan(v,root);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&u!=root){
book[u]=true;
}
if(u==root){
size++;
}
}else{
low[u]=min(low[u],dfn[v]);
}
}
if(size>=2&&u==root){
book[u]=true;
}
}
缩点
#include <iostream>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#define int long long
using namespace std;
const int MAXN=1e5+5;
bool check(int);
void tarjan(int);
void topsort();
vector<int> g[MAXN],G[MAXN];
int indeed[MAXN],belong[MAXN];
int a[MAXN],u[MAXN],v[MAXN];
int f[MAXN];
int n,m,ans;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>u[i]>>v[i];
g[u[i]].push_back(v[i]);
}
for(int i=1;i<=n;i++){
if(!check(i)){
tarjan(i);
}
}
for(int i=1;i<=m;i++){
int x=belong[u[i]],y=belong[v[i]];
if(x!=y){// 顶点不同
G[x].push_back(y);
indeed[y]++;
}
}
topsort();
for(int i=1;i<=n;i++){
ans=max(ans,f[i]);
}
cout<<ans;
return 0;
}
stack<int> s;
bool book[MAXN];
int low[MAXN],dfn[MAXN];
int scc[MAXN];// 节点在强连通分量中的编号
int len[MAXN];// 这个强连通分量的大小
int dfncnt,size;
bool check(int u){
return dfn[u];
}
void tarjan(int u){
low[u]=dfn[u]=++dfncnt;// 赋 dfs 序编号
s.push(u);
book[u]=true;// 在栈中
for(auto v:g[u]){
if(!dfn[v]){// 这个点没有遍历过
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(book[v]){// 在栈中
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){// 强连通分量的起始点
++size;
while(true){
int t=s.top();s.pop();
scc[t]=size,book[t]=false;
belong[t]=u;// 链接点
len[size]++;
if(t==u){
break;
}
a[u]+=a[t];// 缩点
}
}
}
queue<int> q;
void topsort(){// 拓扑排序
for(int i=1;i<=n;i++){
if(i==belong[i]&&!indeed[i]){
q.push(i);
f[i]=a[i];
}
}
while(!q.empty()){
int u=q.front();q.pop();
for(auto v:G[u]){
f[v]=max(f[v],f[u]+a[v]);
indeed[v]--;
if(!indeed[v]){
q.push(v);
}
}
}
}
马拉车算法
//exam: P3805 【模板】Manacher
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 2.2e7+5;
void input();
int solve();
signed main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
input();
cout << solve();
return 0;
}
char s[MAXN];
int f[MAXN];
int size;
void input() { // 读入处理好后的字符串
char c = getchar();
size = 1;
s[0] = '~', s[1] = '|';
while(c < 'a' || c > 'z') { // 跳过无用字符
c = getchar();
}
while('a' <= c && c <= 'z') {
s[++size] = c;
s[++size] = '|'; // 加入分隔符
c = getchar();
}
}
int solve() { // 马拉车算法
int r = 0, mid = 0;
int res = 0;
for(int t = 1; t <= size; t++) {
if(t <= r) {
f[t] = min(f[(mid << 1) - t], r - t + 1);
}
while(s[t - f[t]] == s[t + f[t]]) { // 暴力拓展左右两侧
f[t]++;
}
if(f[t] + t > r) {
r = f[t] + t - 1;
mid = t;
}
res = max(res, f[t]);
}
return res - 1;
}