目录
- O2/O3镇楼
- Fread快读
- [AC自动机,fail树(JZOJ 7044)](https://blog.youkuaiyun.com/wangyuda123456789/article/details/115453883?utm_medium=distribute.pc_relevant.none-task-blog-2~default~OPENSEARCH~default-1.baidujs&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~OPENSEARCH~default-1.baidujs)
- 动态开点,求第K大,插入删除(JZOJ 4270)
- 匈牙利算法(二分图匹配 JZOJ 1156)
- 树链剖分(JZOJ2256)
- 线段树(区间查询,修改)(JZOJ1960)
- Tarjan割点
- Tarjan求桥
- 网络流Dinic
- 网络流SAP
- 线筛( μ , φ \mu,\varphi μ,φ,质因数分解)
- ST表
- 多项式求逆,NTT JZOJ3303
- 洛谷FFT板子P3803
- F W T o r a n d x o r FWT\,or\,and\,xor FWTorandxor 洛谷P4717
- splay 普通平衡树洛谷P3369
- 替罪羊树 普通平衡树洛谷P3369
- 费用流 洛谷P2045K取方格数
- 高斯消元 JZOJ6942作业题,也涉及FWT,[矩阵树定理](https://blog.youkuaiyun.com/wangyuda123456789/article/details/112339065)
- SAM TJOI2015弦论
- PAM JZOJ3291【JSOI2013】快乐的JYY
- 马拉车 洛谷P3805
- 莫比乌斯函数——一些小小的证明
- 普通莫队——小Z的袜子JZOJ1902
- [树上莫队 JZOJ3360苹果树](https://blog.youkuaiyun.com/wangyuda123456789/article/details/95666906)
- 圆方树上最短路 JZOJ1914
- [主席树 JZOJ7050](https://blog.youkuaiyun.com/wangyuda123456789/article/details/115354173)
O2/O3镇楼
#pragma GCC optimize(2)
#pragma GCC optimize(3)
Fread快读
在毒瘤题下能比 g e t c h a r getchar getchar快近 1 s 1s 1s
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(ll &x){
char ch=nc();x=0;
while (!(ch>='0'&&ch<='9')) ch=nc();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=nc();
}
AC自动机,fail树(JZOJ 7044)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 1000005
#define ll long long
#include <vector>
using namespace std;
int trie[N][26],dfn[N],fail[N];
int f[N][3],q[N],size[N],cun[N],ys[N],len[N];
struct node{
ll max,flag;
}tree[N<<1];
ll dp[N],val[N],s;
int i,j,k,m,n,o,p,l,t,tot,now,sum;
char c[N];
vector<int> a[N];
queue<int> h;
void build(int n)
{
int now=0;
for (int i=1;i<=n;i++)
{
if (!trie[now][c[i]-'a'])
trie[now][c[i]-'a']=++sum;
now=trie[now][c[i]-'a'],cun[++cun[0]]=now;
}
}
void insert(int x,int y) {f[++t][1]=y,f[t][2]=q[x],q[x]=t;}
void work()
{
int now=0;
for (i=0;i<=25;i++)
if (trie[now][i]) h.push(trie[now][i]);
while (!h.empty())
{
int st=h.front();h.pop();
for (int i=0;i<=25;i++)
if (trie[st][i]) fail[trie[st][i]]=trie[fail[st]][i],h.push(trie[st][i]);
else trie[st][i]=trie[fail[st]][i];
}
for (i=1;i<=sum;i++) insert(fail[i]+1,i+1);//printf("%d %d\n",fail[i],i);
}
void dg(int t)
{
dfn[t]=++tot,size[t]=1;
for (int k=q[t];k;k=f[k][2])
{
dg(f[k][1]);
size[t]+=size[f[k][1]];
}
}
ll max(ll a,ll b) {return a>b?a:b;}
void downdata(ll x)
{
if (!tree[x].flag) return;
ll k=tree[x].flag;
tree[x<<1].max=max(tree[x<<1].max,k),tree[x<<1|1].max=max(tree[x<<1|1].max,k);
tree[x<<1].flag=max(tree[x<<1].flag,k),tree[x<<1|1].flag=max(tree[x<<1|1].flag,k);
tree[x].flag=0;
}
void change(ll x,ll l,ll r,ll st,ll en,ll ad)
{
if (l>=st&&r<=en) tree[x].max=max(tree[x].max,ad),tree[x].flag=max(tree[x].flag,ad);
else {
downdata(x);
ll mid=(l+r)/2;
if (en<=mid) change(x<<1,l,mid,st,en,ad);
else if (st>mid) change(x<<1|1,mid+1,r,st,en,ad);
else change(x<<1,l,mid,st,mid,ad),change(x<<1|1,mid+1,r,mid+1,en,ad);
tree[x].max=max(tree[x<<1].max,tree[x<<1|1].max);
}
}
ll query(ll x,ll l,ll r,ll pos)
{
if (l==r) return tree[x].max;
else {
downdata(x);
ll mid=(l+r)/2;
if (pos<=mid) return query(x<<1,l,mid,pos);
else return query(x<<1|1,mid+1,r,pos);
}
}
int main()
{
freopen("word.in","r",stdin);
freopen("word.out","w",stdout);
scanf("%d\n",&n);
for (i=1;i<=n;i++)
{
scanf("%s %lld\n",c+1,&val[i]);
cun[0]=0;len[i]=strlen(c+1);
build(len[i]);
for (j=1;j<=cun[0];j++) a[i].push_back(cun[j]);
}
work();
dg(1);
ll ans=0;
for (i=1;i<=n;i++)
{
dp[i]=0;
for (j=0;j<=len[i]-1;j++)
dp[i]=max(dp[i],query(1,1,tot,dfn[a[i][j]+1]));
dp[i]+=val[i];
change(1,1,tot,dfn[a[i][len[i]-1]+1],dfn[a[i][len[i]-1]+1]+size[a[i][len[i]-1]+1]-1,dp[i]);
}
for (i=1;i<=n;i++) ans=(dp[i]>ans?dp[i]:ans);
printf("%lld\n",ans);
return 0;
}
动态开点,求第K大,插入删除(JZOJ 4270)
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int i,j,k,m,n,o,p,l,s,t,x,y,tot;
const int inf=2147483647;
int root[27000001],num[27000001],left[27000001],right[27000001];
long long ans,sum[27000001];
char ch;
void add(int &x,int l,int r,int k,int bz)
{
if (!x) tot++,x=tot;
if (bz) num[x]++,sum[x]+=k;
else num[x]--,sum[x]-=k;
if (l==r) return;
int mid=(l+r)/2;
if (k<=mid) add(left[x],l,mid,k,bz); else add(right[x],mid+1,r,k,bz);
}
int find(int x,int l,int r,int k)
{
if (l==r)
{
ans+=min(num[x],k)*l;
return l;
}
int mid=(l+r)/2;
if (num[right[x]]>=k) return find(right[x],mid+1,r,k);
else {
ans+=sum[right[x]];
return find(left[x],l,mid,k-num[right[x]]);
}
}
int main()
{
freopen("grimoire.in","r",stdin);
freopen("grimoire.out","w",stdout);
scanf("%d%d\n",&n,&m);
for (i=1;i<=m;i++)
{
scanf("%c",&ch);
if (ch=='B')
{
scanf("ORROW %d %d\n",&x,&y);
k=find(root[x],0,inf,x);
add(root[x],0,inf,y,1);
if (y>=k)
add(root[0],0,inf,y,1),add(root[0],0,inf,k,0);
} else {
scanf("ETURN %d %d\n",&x,&y);
k=find(root[x],0,inf,x+1);
add(root[x],0,inf,y,0);
if (y>=k)
add(root[0],0,inf,y,0),add(root[0],0,inf,k,1);
}
ans=0;
find(root[0],0,inf,n);
printf("%lld\n",ans);
}
return 0;
}
匈牙利算法(二分图匹配 JZOJ 1156)
#include <cstdio>
#include <algorithm>
using namespace std;
int i,j,k,m,n,o,p,l,t;
int x[100001],y[100001];
bool line[201][201],bz[201];
int done[100001];
void insert(int x,int y)
{
line[x][y]=true;
}
int find(int x)
{
for (int i=1;i<=n;i++)
{
if (line[x][i]==true&&bz[i]==false)
{
bz[i]=true;
if (!done[i]||find(done[i]))
{
done[i]=x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
scanf("%d",&m);
for (i=1;i<=m;i++) {
scanf("%d%d",&o,&p);
if (x[o]<x[p]) line[o][p]=true;
if (x[o]>x[p]) line[p][o]=true;
}
o=0;
for (i=1;i<=n;i++)
{
for (j=1;j<=n;j++) bz[j]=false;
if (find(i)==true) o++;
}
printf("%d\n",n-o);
}
树链剖分(JZOJ2256)
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
using namespace std;
int i,j,k,m,n,o,p,l,s,t,x,y,tot;
struct node{int sum,max,l,r;}f[1200001];
int ff[600001][3],q[600001],fa[300001],son[300001],dep[300001],size[300001];
int top[300001],tree[300001],pre[300001],a[300001];
char ch[7];
void insert(int x,int y)
{ t++,ff[t][1]=y,ff[t][2]=q[x],q[x]=t; }
void downdata(int x)
{
int xx=x*2,yy=x*2+1;
f[x].sum=f[xx].sum+f[yy].sum;
f[x].max=max(f[xx].max,f[yy].max);
}
void change(int x,int v,int ad)
{
if (f[x].l==f[x].r) f[x].max=ad,f[x].sum=ad;
else {
int mid=(f[x].l+f[x].r)/2;
if (v<=mid) change(x*2,v,ad); else change(x*2+1,v,ad);
downdata(x);
}
}
void make(int x,int l,int r)
{
f[x].l=l,f[x].r=r;
if (l==r) f[x].sum=f[x].max=a[pre[l]];
else {
int mid=(l+r)/2;
make(x*2,l,mid);make(x*2+1,mid+1,r);
downdata(x);
}
}
void dg1(int t)
{
size[t]=1;
for (int k=q[t];k;k=ff[k][2]) {
int h=ff[k][1];
if (h!=fa[t]) {
fa[h]=t,dep[h]=dep[t]+1;
dg1(h);
size[t]+=size[h];
if ((!son[t])||(size[son[t]]<size[h])) son[t]=h;
}
}
}
void dg2(int t,int ad)
{
tot++;
tree[t]=tot,pre[tot]=t,top[t]=ad;
if (!son[t]) return;
dg2(son[t],ad);
for (int k=q[t];k;k=ff[k][2]) {
int h=ff[k][1];
if ((h!=fa[t])&&(h!=son[t])) dg2(h,h);
}
}
int getsum(int t,int x,int y)
{
if ((f[t].l>=x)&&(f[t].r<=y)) return f[t].sum;
int mid=(f[t].l+f[t].r)/2,sum=0;
if (x<=mid) sum+=getsum(t*2,x,y);
if (y>mid) sum+=getsum(t*2+1,x,y);
return sum;
}
int getmax(int t,int x,int y)
{
if ((f[t].l>=x)&&(f[t].r<=y)) return f[t].max;
int mid=(f[t].l+f[t].r)/2,Max=-2147483648;
if (x<=mid) Max=max(Max,getmax(t*2,x,y));
if (y>mid) Max=max(Max,getmax(t*2+1,x,y));
return Max;
}
int findmax(int x,int y)
{
int xx=top[x],yy=top[y],maxans=-2147483648;
while (xx!=yy) {
if (dep[xx]<dep[yy]) swap(xx,yy),swap(x,y);
maxans=max(maxans,getmax(1,tree[xx],tree[x]));
x=fa[xx],xx=top[x];
}
if (dep[x]>dep[y]) swap(x,y);
maxans=max(maxans,getmax(1,tree[x],tree[y]));
return maxans;
}
int findsum(int x,int y)
{
int xx=top[x],yy=top[y],sumans=0;
while (xx!=yy) {
if (dep[xx]<dep[yy]) swap(xx,yy),swap(x,y);
sumans+=getsum(1,tree[xx],tree[x]);
x=fa[xx],xx=top[x];
}
if (dep[x]>dep[y]) swap(x,y);
sumans+=getsum(1,tree[x],tree[y]);
return sumans;
}
int main()
{
scanf("%d",&n);
for (i=1;i<=n-1;i++) {
scanf("%d%d",&x,&y);
insert(x,y);insert(y,x);
}
for (i=1;i<=n;i++) scanf("%d",&a[i]);
t=0;dep[1]=1;
dg1(1);
dg2(1,1);
make(1,1,n);
scanf("%d",&m);
for (i=1;i<=m;i++) {
scanf("%s",&ch);
scanf("%d%d",&x,&y);
if (ch[1]=='H') {
change(1,tree[x],y);
} else {
printf("%d\n",ch[1]=='M'?findmax(x,y):findsum(x,y));
}
}
}
线段树(区间查询,修改)(JZOJ1960)
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
int i,j,k,m,n,o,p,l,s,t,x,y,w,z;
long long ans;
long long tree[1000001],flag[1000001];
int a[1000001];
void down(int x)
{
int k=flag[x];
flag[x*2]+=k;flag[x*2+1]+=k;tree[x*2]+=k;tree[x*2+1]+=k;
flag[x]=0;
}
void make(int x,int l,int r)
{
if (l==r) tree[x]=a[l];
else {
int mid=(l+r)/2;
make(x*2,l,mid);make(x*2+1,mid+1,r);
tree[x]=max(tree[x*2],tree[x*2+1]);
}
}
void change(int x,int l,int r,int zuo,int you,int h)
{
if (l>=zuo&&r<=you) {
tree[x]+=h;flag[x]+=h;return;
}
down(x);
int mid=(l+r)/2;
if (you<=mid) change(x*2,l,mid,zuo,you,h);
else if (zuo>mid) change(x*2+1,mid+1,r,zuo,you,h);
else change(x*2,l,mid,zuo,you,h),change(x*2+1,mid+1,r,zuo,you,h);
tree[x]=max(tree[x*2],tree[x*2+1]);
}
void find(int x,int l,int r,int st,int en)
{
if (l>=st&&r<=en) {
ans=max(ans,tree[x]);return;
} else {
down(x);
int mid=(l+r)/2;
if (en<=mid) find(x*2,l,mid,st,en);
else if (st>mid) find(x*2+1,mid+1,r,st,en);
else find(x*2,l,mid,st,mid),find(x*2+1,mid+1,r,mid+1,en);
}
}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%d",&a[i]);
make(1,1,n);
scanf("%d",&m);
for (i=1;i<=m;i++){
scanf("%d",&z);
if (z==2) {
scanf("%d%d",&x,&y);
ans=-2147483647;
find(1,1,n,x,y);
printf("%d\n",ans);
} else {
scanf("%d%d%d",&x,&y,&w);
change(1,1,n,x,y,w);
}
}
return 0;
}
Tarjan割点
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
int y,next;
}a[210000];int len,last[110000],bk[110000];
int dfn[110000],low[110000],sum=0,fa[110000],deep[110000];
int mymin(int x,int y) {return x<y?x:y;}
int ju(int x) {return x%2==1?x+1:x-1;}
void ins(int x,int y)
{
a[++len].y=y;a[len].next=last[x];last[x]=len;
}
void dfs(int x,int ma)
{
dfn[x]=low[x]=++sum;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(dfn[y]==0)
{
fa[y]=x;deep[y]=deep[x]+1;dfs(y,k);
low[x]=mymin(low[x],low[y]);
}
else if(ju(ma)!=k) low[x]=mymin(low[x],low[y]);
}
}
int x[110000],y[110000];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
len=0;memset(last,0,sizeof(last));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x[i],&y[i]);
ins(x[i],y[i]);ins(y[i],x[i]);
}
memset(dfn,0,sizeof(dfn));memset(deep,0,sizeof(deep));
for(int i=1;i<=n;i++) if(dfn[i]==0) deep[i]=1,dfs(i,0);
memset(bk,0,sizeof(bk));
for(int i=1;i<=n;i++)
{
if(low[i]>=dfn[fa[i]]) bk[fa[i]]++;
}
for(int i=1;i<=n;i++)
{
if((deep[i]==1&&bk[i]>=2)||(deep[i]>1&&bk[i]>=1)) printf("%d\n",i);
}
return 0;
}
Tarjan求桥
#include<cstdio>
#include<cstring>
using namespace std;
int total,num,root;
int head[200001],next[200001],edge[200001],dfn[200001],low[200001];
bool bz[200001];
void add(int x,int y)
{
total++;
next[total]=head[x];
head[x]=total;
edge[total]=y;
}
void tarjan(int x,int ma)
{
num++;
dfn[x]=num;
low[x]=num;
int number=0;
for (int i=head[x];i;i=next[i])
{
int y=edge[i];
if (dfn[y]==0)
{
tarjan(y,i);
if (low[x]>low[y])
{
low[x]=low[y];
}
if (dfn[x]<=low[y])
{
number++;
if ((x!=root)||(number>1))
{
bz[x]=true;
}
}
}
else
{
if ((y!=edge[ma^1])&&(low[x]>low[y]))
{
low[x]=low[y];
}
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
total=1;
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
memset(bz,false,sizeof(bz));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
num=0;
for (int i=1;i<=n;i++)
{
if (dfn[i]==0)
{
root=i;
tarjan(i,0);
}
}
for (int i=1;i<=n;i++)
{
if (bz[i]==true)
{
printf("%d\n",i);
}
}
}
网络流Dinic
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,s,t,total,next[2000001],head[2000001],edge[2000001],v[2000001],h[2000001],d[2000001];
void insert(int x,int y,int z)
{
total++;
next[total]=head[x];
head[x]=total;
edge[total]=y;
v[total]=z;
}
bool bfs()
{
memset(d,0,sizeof(d));
int l=1,r=1;
h[1]=s;
d[s]=1;
while (l<=r)
{
int u=h[l];
for (int i=head[u];i;i=next[i])
{
int y=edge[i];
if (v[i]&&!d[y])
{
r++;
h[r]=y;
d[y]=d[u]+1;
if (y==t) return true;
}
}
l++;
}
return false;
}
int dinic(int k,int flow)
{
if (k==t) return flow;
int rest=flow;
for (int i=head[k];i && rest;i=next[i])
{
int y=edge[i];
if (v[i]&&d[y]==d[k]+1)
{
int cost;
if (rest>v[i]) cost=v[i];
else cost=rest;
int pay=dinic(y,cost);
if (pay==0) d[y]=0;
rest-=pay;
v[i]-=pay;
v[i^1]+=pay;
}
}
return flow-rest;
}
int main()
{
scanf("%d%d",&m,&n);
s=1;
t=n;
total=1;
for (int i=1;i<=m;i++)
{
int x1,y1,z1;
scanf("%d%d%d",&x1,&y1,&z1);
insert(x1,y1,z1);
insert(y1,x1,0);
insert(y1,x1,z1);
insert(x1,y1,0);
}
int maxflow=0;
int flow;
while (bfs())
while (flow=dinic(s,999999999)) maxflow+=flow;
printf("%d",maxflow);
}
网络流SAP
ll dfs(ll t,ll flow)
{
if (t==T) return flow;
ll have=0;
for (ll k=cur[t];k;k=f[k][2])
{
if (dis[f[k][1]]+1==dis[t]&&f[k][3])
{
cur[t]=k;
ll now=dfs(f[k][1],min(flow-have,f[k][3]));
f[k][3]-=now,f[k^1][3]+=now,have+=now;
if (flow==have) return flow;
}
}
cur[t]=q[t];
if (!(--gap[dis[t]])) dis[S]=T;
++gap[++dis[t]];
return have;
}
线筛( μ , φ \mu,\varphi μ,φ,质因数分解)
mu[1]=phi[1]=1;
for (R int i=2;i<=m;i++)
{
if (!bz[i]) pr[++pr[0]]=i,mu[i]=-1,phi[i]=i-1,mn[i]=i;
for (R int j=1;j<=pr[0]&&pr[j]*i<=m;j++)
{
bz[i*pr[j]]=1,mn[i*pr[j]]=pr[j];
if (!(i%pr[j])) {
phi[i*pr[j]]=phi[i]*pr[j];break;
}
else mu[i*pr[j]]=-mu[i],phi[i*pr[j]]=phi[i]*(pr[j]-1);
}
}
ST表
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100005
using namespace std;
int a[N];
int i,j,k,m,n,o,p,l,s,t,x,y;
struct node{
int lg[N],st[N][18];
int max(int a,int b) {return a>b?a:b;}
void prepare()
{
lg[0]=-1;
for (int i=1;i<=n;i++) lg[i]=lg[i>>1]+1,st[i][0]=a[i];
for (int i=1;i<=17;i++)
for (int j=1;j+(1<<(i-1))<=n;j++)
st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
int query(int x,int y)
{
int k=lg[y-x+1];
return max(st[x][k],st[y-(1<<k)+1][k]);
}
}ST;
void read(int &x)
{
char ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
freopen("Mourinho.in","r",stdin);
freopen("Mourinho.out","w",stdout);
read(n),read(m);
for (i=1;i<=n;i++) read(a[i]);
ST.prepare();
for (i=1;i<=m;i++)
read(x),read(y),printf("%d\n",ST.query(x,y));
return 0;
}
多项式求逆,NTT JZOJ3303
#include<bits/stdc++.h>
#define G 3
#define ll long long
#define o3 inline
using namespace std;
int mod=1004535809;
int i,j,k,m,n,o,p,l,s,t,invG;
int f[2000001],inv[600001],fac[600001];
int a[600001],b[600001],c[600001],d[600001],r[600001];
o3 int ksm(int o,ll p)
{
int s=1,t=o;
while (p>0)
{
if (p%2) s=(ll)s*t%mod;
t=(ll)t*t%mod,p/=2;
}
return s;
}
o3 int pow(int o,int p)
{
int s=1,t=o;
while (p>0)
{
if (p%2) s=(ll)s*t%mod;
t=(ll)t*t%mod,p/=2;
}
return s;
}
o3 int NTT(int *f,int n,int op)
{
for (register int i=0;i<n;i++)
if (r[i]<i) swap(f[i],f[r[i]]);
for (register int p=2;p<=n;p*=2)
{
int len=p/2,w=pow(op==1?G:invG,(mod-1)/p);
for (register int k=0;k<n;k+=p)
{
int buf=1;
for (register int i=k;i<k+len;i++)
{
int temp=(ll)f[len+i]*buf%mod;
f[len+i]=(f[i]-temp+mod)%mod;
f[i]=(f[i]+temp)%mod;buf=(ll)buf*w%mod;
}
}
}
if (op==-1)
{
int invN=pow(n,mod-2);
for (register int i=0;i<n;i++) f[i]=(ll)f[i]*invN%mod;
}
}
o3 void getni(int deg,int *a,int *b,int *tmp)
{
if (deg==1) {
b[0]=pow(a[0],mod-2);return;
}
getni((deg+1)/2,a,b,tmp);
int m=1;while (m<deg*2) m*=2;
memset(r,0,sizeof(r));
copy(a,a+deg,tmp);fill(tmp+deg,tmp+m,0);
for (register int i=1;i<m;i++)
{
r[i]=((r[i>>1]>>1)|((i&1)*(m>>1)));
}
NTT(tmp,m,1);
NTT(b,m,1);
for (register int i=0;i<m;i++)
{
b[i]=(ll)b[i]*(2-(ll)b[i]*tmp[i]%mod)%mod;
if (b[i]<0) b[i]+=mod;
}
NTT(b,m,-1);fill(b+deg,b+m,0);
}
int main()
{
scanf("%d",&n);
invG=pow(G,mod-2);
m=1;while (m<n*2) m*=2;
fac[0]=fac[1]=inv[0]=inv[1]=1;
for (i=1;i<=m;i++) fac[i]=(ll)fac[i-1]*i%mod,inv[i]=(ll)inv[i-1]*pow(i,mod-2)%mod;
d[0]=0;a[0]=a[1]=d[1]=1;
for (i=2;i<=n;i++)
{
ll ggg=i;ggg=ggg*(ggg-1)/2;
a[i]=(ll)ksm(2,ggg)*inv[i]%mod;
}
getni(m,a,b,c);
for (i=2;i<=n;i++) {
ll ggg=i;ggg=ggg*(ggg-1)/2;
d[i]=(ll)ksm(2,ggg)*inv[i-1]%mod;
}
for (int i=1;i<=m;i++)
r[i]=(r[i>>1]>>1)|(i&1?m>>1:0);
NTT(b,m,1),NTT(d,m,1);
for (int i=0;i<=m;i++) b[i]=(ll)b[i]*d[i]%mod;
NTT(b,m,-1);
long long ans=(ll)b[n]*fac[n-1]%mod;
printf("%lld\n",ans);
return 0;
}
洛谷FFT板子P3803
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <complex>
#include <cmath>
#define N 2100005
using namespace std;
const double Pi=acos(-1);
int i,j,k,m,n,o,p,l,s,t;
complex<double> a[N],b[N];
int r[N];
void read_double(complex<double> &x)
{
char ch=getchar();x=0;int f=(ch=='-'?-1:1);
while (ch<'0'||ch>'9') ch=getchar(),f=(ch=='-'?-1:f);
while (ch>='0'&&ch<='9') x=x.real()*10+ch-48,ch=getchar();
x*=f;
}
void read_int(int &x)
{
char ch=getchar();x=0;int f=(ch=='-'?-1:1);
while (ch<'0'||ch>'9') ch=getchar(),f=(ch=='-'?-1:f);
while (ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
x*=f;
}
void FFT(complex<double> *a,int opt)
{
for (int i=0;i<n;i++)
if (i<r[i]) swap(a[i],a[r[i]]);
for (int i=1;i<n;i<<=1)
{
complex<double> W(cos(Pi/i),opt*sin(Pi/i));
for (int p=i<<1,j=0;j<n;j+=p)
{
complex<double> w(1,0);
for (int k=0;k<i;k++,w*=W)
{
complex<double> x=a[j+k],y=a[i+j+k]*w;
a[j+k]=x+y,a[i+j+k]=x-y;
}
}
}
}
int main()
{
read_int(n),read_int(m);
for (i=0;i<=n;i++) read_double(a[i]);
for (i=0;i<=m;i++) read_double(b[i]);
m+=n;
for (n=1;n<=m;n<<=1) l++;
for (i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
FFT(a,1),FFT(b,1);
for (i=0;i<=n;i++) a[i]=a[i]*b[i];
FFT(a,-1);
for (i=0;i<=m;i++)
printf("%.0lf ",floor(a[i].real()/n+0.5));
return 0;
}
F W T o r a n d x o r FWT\,or\,and\,xor FWTorandxor 洛谷P4717
#include <cstdio>
#include <cstring>
#include <algorithm>
#define mo 998244353
#define inv2 499122177
#define ll long long
#define N 1000005
using namespace std;
ll f[N],g[N],a[N],b[N];
ll i,j,k,m,n,o,p,l,s,t;
void FWT_or(ll *a,ll opt)
{
for (ll i=1;i<n;i<<=1)
for (ll p=i<<1,j=0;j<n;j+=p)
for (ll k=0;k<i;k++)
a[i+j+k]+=a[j+k]*opt,a[i+j+k]=(a[i+j+k]+mo)%mo;
}
void FWT_and(ll *a,ll opt)
{
for (ll i=1;i<n;i<<=1)
for (ll p=i<<1,j=0;j<n;j+=p)
for (ll k=0;k<i;k++)
a[j+k]+=a[i+j+k]*opt,a[j+k]=(a[j+k]+mo)%mo;
}
void FWT_xor(ll *a,ll opt)
{
for (ll i=1;i<n;i<<=1)
for (ll p=i<<1,j=0;j<n;j+=p)
for (ll k=0;k<i;k++)
{
ll x=a[j+k],y=a[i+j+k];
a[j+k]=(x+y)%mo,a[i+j+k]=(x-y+mo)%mo;
if (opt==-1) a[j+k]=a[j+k]*inv2%mo,a[i+j+k]=a[i+j+k]*inv2%mo;
}
}
void read(ll &x)
{
char ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
freopen("FWT.in","r",stdin);
freopen("FWT.out","w",stdout);
read(n);n=1<<n;
for (i=0;i<n;i++) read(f[i]);
for (i=0;i<n;i++) read(g[i]);
memcpy(a,f,sizeof(a)),memcpy(b,g,sizeof(b));
FWT_or(f,1),FWT_or(g,1);
for (i=0;i<n;i++) f[i]=f[i]*g[i]%mo;
FWT_or(f,-1);
for (i=0;i<n;i++) printf("%lld ",f[i]);
puts("");
memcpy(f,a,sizeof(f)),memcpy(g,b,sizeof(g));
FWT_and(f,1),FWT_and(g,1);
for (i=0;i<n;i++) f[i]=f[i]*g[i]%mo;
FWT_and(f,-1);
for (i=0;i<n;i++) printf("%lld ",f[i]);
puts("");
memcpy(f,a,sizeof(f)),memcpy(g,b,sizeof(g));
FWT_xor(f,1),FWT_xor(g,1);
for (i=0;i<n;i++) f[i]=f[i]*g[i]%mo;
FWT_xor(f,-1);
for (i=0;i<n;i++) printf("%lld ",f[i]);
puts("");
return 0;
}
splay 普通平衡树洛谷P3369
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node{
int size,cnt,key,fa;
}tree[1000001];
int son[1000001][2];
int i,j,k,m,n,o,p,l,s,t,root,len,ihds;
void clear(int x) {tree[x].size=tree[x].cnt=tree[x].key=tree[x].fa=0;son[x][0]=son[x][1]=0;}
void update(int x)
{
if (!x) return;
tree[x].size=tree[x].cnt;
if (son[x][0]) tree[x].size+=tree[son[x][0]].size;
if (son[x][1]) tree[x].size+=tree[son[x][1]].size;
}
int get(int x) {return son[tree[x].fa][1]==x;}
void rotate(int x)
{
int fa=tree[x].fa,grandpa=tree[fa].fa,wx=get(x),wfa=grandpa&&get(fa);
son[fa][wx]=son[x][wx^1],tree[son[fa][wx]].fa=fa;
son[x][wx^1]=fa,tree[fa].fa=x;tree[x].fa=grandpa;
if (grandpa) son[grandpa][wfa]=x;
update(fa);update(x);
}
void splay(int x)
{
for (int fa;fa=tree[x].fa;rotate(x))
{
if (tree[fa].fa) rotate(get(x)==get(fa)?fa:x);
}
root=x;
}
void insert(int x)
{
if (!root) {
len++,tree[1].fa=0;tree[1].size=tree[1].cnt=1;tree[1].key=x,son[1][0]=son[1][1]=0,root=1;
} else {
int now=root,fa;
while (1)
{
if (x==tree[now].key)
{
tree[now].cnt++;update(now),update(tree[now].fa);splay(now);break;
}
fa=now,now=son[now][tree[now].key<x];
if (!now)
{
len++,tree[len].fa=fa,tree[len].size=tree[len].cnt=1;tree[len].key=x;son[len][0]=son[len][1]=0;son[fa][tree[fa].key<x]=len;update(fa);splay(len);break;
}
}
}
}
int queryrank(int x)
{
int now=root,ans=0;
while (1)
{
if (tree[now].key>x) now=son[now][0];
else {
ans+=tree[son[now][0]].size;
if (tree[now].key==x) {splay(now);return ans+1;}
ans+=tree[now].cnt,now=son[now][1];
}
}
}
int querynumber(int x)
{
int now=root;
while (1)
{
if (son[now][0]&&tree[son[now][0]].size>=x) now=son[now][0];
else {
int comp=tree[son[now][0]].size+tree[now].cnt;
if (x<=comp) return tree[now].key;
x-=comp,now=son[now][1];
}
}
}
int pre()
{
int now=root;
now=son[now][0];
while (son[now][1]) now=son[now][1];
return now;
}
int nxt()
{
int now=root;
now=son[now][1];
while (son[now][0]) now=son[now][0];
return now;
}
void del(int x)
{
queryrank(x);
if (tree[root].cnt>1) {tree[root].cnt--;update(root);return;}
if (!son[root][0]&&!son[root][1]) {clear(root);root=0;return;}
if (!son[root][0])
{
int oldroot=root;root=son[root][1];tree[root].fa=0;clear(oldroot);return;
} else if (!son[root][1])
{
int oldroot=root;root=son[root][0];tree[root].fa=0;clear(oldroot);return;
}
int pr=pre(),oldroot=root;splay(pr);
son[pr][1]=son[oldroot][1],tree[son[oldroot][1]].fa=root;clear(oldroot);update(root);
}
int main()
{
freopen("splay.in","r",stdin);
freopen("splay.out","w",stdout);
scanf("%d",&t);
while (t--)
{
scanf("%d%d",&o,&p);
if (p==3)
{
int fdsa=0;
}
if (o==1) insert(p);
else if (o==2) del(p);
else if (o==3) printf("%d\n",queryrank(p));
else if (o==4) printf("%d\n",querynumber(p));
else if (o==5) insert(p),
printf("%d\n",tree[pre()].key),del(p);
else if (o==6) insert(p),printf("%d\n",tree[nxt()].key),del(p);
}
return 0;
}
替罪羊树 普通平衡树洛谷P3369
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000005
using namespace std;
struct node{
int x,zuo,you,fa,size,trsize,whsize,tot;bool tf;
}tree[N];
struct wyd{
int x,tot;
}shulie[N];
int ck[N];
int i,j,k,m,n,o,p,l,s,t,tt,len,root,x,y;
double alpha=0.75;
void updata(int now,int x,int y,int z)
{
if (!now) return;
tree[now].trsize+=x;tree[now].size+=y,tree[now].whsize+=z;
updata(tree[now].fa,x,y,z);
}
int kk()
{
return t>0?ck[t--]:++len;
}
int find(int x,int now)
{
if (x<tree[now].x&&tree[now].zuo) return find(x,tree[now].zuo);
if (x>tree[now].x&&tree[now].you) return find(x,tree[now].you);
return now;
}
int build(int x,int now,int fa)
{
tree[now].x=x;tree[now].zuo=tree[now].you=0;tree[now].fa=fa;
tree[now].size=tree[now].trsize=tree[now].whsize=tree[now].tot=1;
tree[now].tf=false;
}
void dfs_rebuild(int now)
{
if (!now) return;
dfs_rebuild(tree[now].zuo);
if (!tree[now].tf)
{
shulie[++tt].x=tree[now].x,shulie[tt].tot=tree[now].tot;
}
ck[++t]=now;
dfs_rebuild(tree[now].you);
}
int readd(int l,int r,int fa)
{
if (o==5)
{
o=o;
}
if (l>r) return 0;
int mid=(l+r)/2;int now=kk();
tree[now].fa=fa;
tree[now].x=shulie[mid].x;
tree[now].tot=shulie[mid].tot;
tree[now].zuo=readd(l,mid-1,now);
tree[now].you=readd(mid+1,r,now);
tree[now].size=tree[now].trsize=r-l+1;
tree[now].whsize=tree[tree[now].zuo].whsize+tree[tree[now].you].whsize+shulie[mid].tot;
tree[now].tf=false;
return now;
}
void rebuild(int x)
{
tt=0;
dfs_rebuild(x);
if (x==root) {
root=readd(1,tt,0);return;
}
updata(tree[x].fa,tree[x].trsize-tree[x].size,0,0);
if (tree[tree[x].fa].zuo==x) tree[tree[x].fa].zuo=readd(1,tt,tree[x].fa);
else tree[tree[x].fa].you=readd(1,tt,tree[x].fa);
}
void find_rebuild(int now,int x)
{
if ((double)tree[tree[now].zuo].size>(double)tree[now].size*alpha||
(double)tree[tree[now].you].size>(double)tree[now].size*alpha||
(double)tree[now].size-(double)tree[now].trsize>(double)tree[now].size*0.3)
{
rebuild(now);
return;
}
if (tree[now].x!=x)
find_rebuild(x<tree[now].x?tree[now].zuo:tree[now].you,x);
}
void add(int x)
{
if (root==0)
{
build(x,root=kk(),0);
return;
}
int p=find(x,root);
if (x==tree[p].x)
{
tree[p].tot++;
if (tree[p].tf) tree[p].tf=false,updata(p,1,0,1);
else updata(p,0,0,1);
}
else if (x<tree[p].x) build(x,tree[p].zuo=kk(),p),updata(p,1,1,1);
else build(x,tree[p].you=kk(),p),updata(p,1,1,1);
find_rebuild(root,x);
}
void del(int x)
{
if (o==18)
{
o=o;
}
int p=find(x,root);
tree[p].tot--;
if (!tree[p].tot) updata(p,-1,0,-1),tree[p].tf=true;
else updata(p,0,0,-1);
find_rebuild(root,x);
}
int findxpm(int x)
{
int now=root,ans=0;
while (tree[now].x!=x)
{
if (x<tree[now].x) now=tree[now].zuo;
else ans+=tree[now].tot+tree[tree[now].zuo].whsize,now=tree[now].you;
}
ans+=tree[tree[now].zuo].whsize;
return ans+1;
}
int findmpx(int x)
{
if (o==42)
{
o=o;
}
int now=root;
while (0<1)
{
if (x<=tree[tree[now].zuo].whsize) now=tree[now].zuo;
else {
x-=tree[tree[now].zuo].whsize;
if (tree[now].tot>=x)
{
return tree[now].x;
}x-=tree[now].tot;
now=tree[now].you;
}
}
}
int pre(int x)
{
add(x);
int tmp=findxpm(x);
del(x);
return findmpx(tmp-1);
}
int nxt(int x)
{
add(x+1);
int tmp=findxpm(x+1);
del(x+1);
return findmpx(tmp);
}
int main()
{
scanf("%d",&o);
while (o--)
{
scanf("%d%d",&x,&y);
if (x==1) add(y);
if (x==2) del(y);
if (o==42)
{
o=o;
}
if (x==3) printf("%d\n",findxpm(y));
if (x==4) printf("%d\n",findmpx(y));
if (x==5) printf("%d\n",pre(y));
if (x==6) printf("%d\n",nxt(y));
}
return 0;
}
费用流 洛谷P2045K取方格数
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int f[200005][5],q[10005];
int dist[10005],flow[10005],spfa[10005],pre[10005],last[10005];
int i,j,k,m,n,o,p,l,s,t,S,T,times,c,ans;
void insert(int x,int y,int z,int w) {
f[++t][1]=y,f[t][2]=q[x],f[t][3]=z,f[t][4]=w,q[x]=t;
f[++t][1]=x,f[t][2]=q[y],f[t][3]=0,f[t][4]=-w,q[y]=t;
}
int num(int x,int y,int z) {return x*n*n+(y-1)*n+z;}
int costflow()
{
queue<int>h;
memset(dist,-1,sizeof(dist));memset(spfa,0,sizeof(spfa));
h.push(S);flow[S]=1e9;dist[S]=0;spfa[S]=1;
while (!h.empty())
{
int st=h.front();h.pop();
for (int k=q[st];k;k=f[k][2])
{
if (!f[k][3]) continue;
if (dist[st]+f[k][4]>dist[f[k][1]])
{
dist[f[k][1]]=dist[st]+f[k][4];
flow[f[k][1]]=min(flow[st],f[k][3]);pre[f[k][1]]=k;
if (!spfa[f[k][1]]) h.push(f[k][1]),spfa[f[k][1]]=1;
}
}spfa[st]=0;
}
return dist[T]!=-1;
}
void update()
{
ans+=dist[T]*flow[T];
int k=T;
while (k!=S)
{
f[pre[k]][3]-=flow[T];
f[pre[k]^1][3]+=flow[T];
k=f[pre[k]^1][1];
}
}
int read(int &x)
{
char ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
read(n),read(times);t=1;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
read(c);
insert(num(0,i,j),num(1,i,j),1,c);
insert(num(0,i,j),num(1,i,j),times-1,0);
if (i<n) insert(num(1,i,j),num(0,i+1,j),times,0);
if (j<n) insert(num(1,i,j),num(0,i,j+1),times,0);
}
S=1,T=2*n*n;
while (costflow())
update();
printf("%d\n",ans);
return 0;
}
高斯消元 JZOJ6942作业题,也涉及FWT,矩阵树定理
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define mo 998244353
#define inv2 499122177
using namespace std;
ll i,j,k,m,n,o,p,l,s,t,ans;
struct node{
ll x,y,z;
}a[10005];
ll b[10005][513],c[513],d[513];
ll f[65][65];
void FWT(ll *a,ll opt)
{
for (ll i=1;i<256;i<<=1)
for (ll p=i<<1,j=0;j<256;j+=p)
for (ll k=0;k<i;++k)
{
ll X=a[j+k],Y=a[i+j+k];
a[j+k]=X+Y;a[i+j+k]=(X-Y+mo)%mo;
if (opt==-1)
a[j+k]=a[j+k]*inv2%mo,a[i+j+k]=a[i+j+k]*inv2%mo;
}
}
void read(ll &x)
{
char ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
void add(ll x,ll y,ll z)
{
f[x][x]+=z,f[x][y]+=-z;f[x][x]%=mo,f[x][y]%=mo;//血泪教训,这里一定要取模!
}
int main()
{
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
read(n),read(m);
for (i=1;i<=m;i++) read(a[i].x),read(a[i].y),read(a[i].z);
for (i=1;i<=m;i++)
{
memset(c,0,sizeof(c));
c[a[i].z]=1;
FWT(c,1);
memcpy(b[i],c,sizeof(b[i]));
}
for (p=0;p<=255;p++)
{
if (p==15)
{
int sfgx=0;
}
memset(f,0,sizeof(f));
for (i=1;i<=m;i++)
add(a[i].x,a[i].y,b[i][p]),add(a[i].y,a[i].x,b[i][p]);
s=1;
for (i=1;i<=n-1;i++)
{
for (j=i+1;j<=n-1;j++)
{
while (f[j][i])
{
o=f[i][i]/f[j][i];
for (k=i;k<=n-1;k++)
f[i][k]=(f[i][k]-(o*f[j][k]%mo)+mo)%mo;
swap(f[i],f[j]);
s=-s;
}
}
s=s*f[i][i]%mo;
}
d[p]=s;
}
FWT(d,-1);
for (i=0;i<=255;i++)
ans=(ans+(i*d[i]%mo)+mo)%mo;
printf("%lld\n",ans);
return 0;
}
SAM TJOI2015弦论
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int dep[1000001],fa[1000001],t[1000001][27];
int f[1000001],b[1000001],sum[1000001],g[1000001];
char c[1000001];
int i,j,k,m,n,o,p,l,s,last,q,tot,opt;
int push(int x) {dep[++tot]=x;return tot;}
void ins(int c)
{
int np=push(dep[last]+1),p=last;g[np]=1;
for (;p&&!t[p][c];p=fa[p]) t[p][c]=np;
if (!p) fa[np]=1;
else {
int q=t[p][c];
if (dep[q]==dep[p]+1) fa[np]=q;
else {
int nq=push(dep[p]+1);
fa[nq]=fa[q],fa[q]=fa[np]=nq;
memcpy(t[nq],t[q],sizeof(t[nq]));
for (;p&&t[p][c]==q;p=fa[p]) t[p][c]=nq;
}
}last=np;
}
int work(int k)
{
int x=1;
while (1)
{
if (k<=g[x]) return 0;k-=g[x];
for (int i=0;i<=25;i++)
{
if (!t[x][i]) continue;
if (k<=sum[t[x][i]])
{
putchar('a'+i);
x=t[x][i];break;
}k-=sum[t[x][i]];
}
}
}
int main()
{
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
scanf("%s\n",c+1);
scanf("%d%d",&opt,&k);tot=last=1;n=strlen(c+1);
for (i=1;i<=n;i++)
{
ins(c[i]-'a');
}
for (i=1;i<=tot;i++) b[dep[i]]++;
for (i=1;i<=n;i++) b[i]+=b[i-1];
for (i=tot;i>=1;i--) f[b[dep[i]]--]=i;
for (i=tot;i>=1;i--)
{
if (opt) g[fa[f[i]]]+=g[f[i]];
else g[f[i]]=1;
}g[1]=0;
for (i=tot;i>=1;i--)
{
for (j=0;j<=25;j++) sum[f[i]]+=sum[t[f[i]][j]];
sum[f[i]]+=g[f[i]];
}
if (sum[1]<k)
{
puts("-1");return 0;
}
work(k);
return 0;
}
PAM JZOJ3291【JSOI2013】快乐的JYY
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int i,j,k,m,n,o,p,l,s,t;
struct node{
int son[26],sum1,sum2,fa,len;
}pam[100005];
char a[100005],b[100005];
int i,j,k,m,n,o,p,l,s,t,tot,last;
long long ans;
void insert(char c,int n)
{
int p=last;
while (a[n-pam[p].len-1]!=a[n]) p=pam[p].fa;
if (!pam[p].son[c])
{
int q=++tot,Fa=pam[p].fa;
pam[q].len=pam[p].len+2,pam[p].son[c]=q;
while (a[n-pam[Fa].len-1]!=a[n]) Fa=pam[Fa].fa;
pam[q].fa=pam[Fa].son[c];
}
last=pam[p].son[c],pam[last].sum1++;
}
void find(char c,int n)
{
int p=last;
while (p!=1&&(a[n-pam[p].len-1]!=a[n]||!pam[p].son[c])) p=pam[p].fa;
if (p==1)
{
last=1;return;
}
last=pam[p].son[c],pam[last].sum2++;
}
int main()
{
scanf("%s\n",a+1),n=strlen(a+1);
scanf("%s\n",b+1),m=strlen(b+1);
a[0]='#',b[0]='#';tot=1,pam[0].len=-1,pam[0].fa=1;
for (i=1;i<=n;i++) insert(a[i]-'A',i);
last=0;
for (i=1;i<=m;i++) find(b[i]-'A',i);
for (i=tot;i>=2;i--) pam[fa[i]].sum1+=pam[i].sum1,pam[fa[i]].sum2+=pam[i].sum2,ans+=1ll*pam[i].sum1*pam[i].sum2;
printf("%lld\n",ans);
}
马拉车 洛谷P3805
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[30000005],a[12000005];
int p[32000005];
int i,j,k,m,n,o,l,t,len,mid,mx,ans;
int main()
{
// freopen("manacher.in","r",stdin);
// freopen("manacher.out","w",stdout);
scanf("%s",a+1);
int len=strlen(a+1);
s[0]='(';s[1]='#';l=1;
for (i=1;i<=len;i++) s[++l]=a[i],s[++l]='#';
s[++l]=')';len=l;
mid=mx=ans=1;
for (i=1;i<len;i++)
{
if (i<mx) p[i]=min(p[mid*2-i],mx-i);
else p[i]=1;
while (s[i-p[i]]==s[i+p[i]]) p[i]++;
if (i+p[i]>mx) mx=i+p[i],mid=i;
ans=max(ans,p[i]-1);
printf("%d %c\n",p[i]-1,s[i]);
}
printf("%d\n",ans);
}
莫比乌斯函数——一些小小的证明
普通莫队——小Z的袜子JZOJ1902
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
struct node{
long long l,r,a,b,id;
}q[100005];
long long a[100005],sum[100005],b[100005];
long long i,j,k,m,n,o,p,l,s,t,unit,r,ans;
bool cmpx(node x,node y)
{
return b[x.l]==b[y.l]?x.r<y.r:x.l<y.l;
}
long long work(long long x,long long add)
{
ans-=sum[a[x]]*sum[a[x]],sum[a[x]]+=add,ans+=sum[a[x]]*sum[a[x]];
}
long long getgcd(long long x,long long y)
{
return !(x%y)?y:getgcd(y,x%y);
}
long long cmpy(node x,node y)
{
return x.id<y.id;
}
int main()
{
freopen("socks.in","r",stdin);
freopen("socks.out","w",stdout);
scanf("%lld%lld",&n,&m);unit=sqrt(n);
for (i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=i/unit+1;
for (i=1;i<=m;i++) scanf("%lld%lld",&q[i].l,&q[i].r),q[i].id=i;
sort(q+1,q+m+1,cmpx);l=1,r=0;
for (i=1;i<=m;i++)
{
while (l<q[i].l) work(l,-1),l++;
while (l>q[i].l) work(l-1,1),l--;
while (r<q[i].r) work(r+1,1),r++;
while (r>q[i].r) work(r,-1),r--;
if (q[i].l==q[i].r) {
q[i].a=0,q[i].b=1;continue;
}long long len=q[i].r-q[i].l+1;
q[i].a=ans-len;q[i].b=len*(len-1);
long long gcd=getgcd(q[i].a,q[i].b);
q[i].a/=gcd,q[i].b/=gcd;
}
sort(q+1,q+m+1,cmpy);
for (i=1;i<=m;i++) printf("%lld/%lld\n",q[i].a,q[i].b);
return 0;
}
树上莫队 JZOJ3360苹果树
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int block[100001],dfn[100001],sta[100001];
int f[200001][4],q[200001],ans[200001],co[200001];
int b[200001][17],mi[200001],num[200001],dep[200001];
bool a[100001];
struct node{
int x,y,a,b,id;
}que[100005];
int i,j,k,m,n,o,p,l,s,t,sum,now,tot,root,top,bg,g;
void insert(int x,int y)
{
f[++t][1]=y,f[t][2]=q[x],q[x]=t;
}
int dg(int t,int fa)
{
int size=0;
dfn[t]=++tot;
for (int k=q[t];k;k=f[k][2])
{
if (f[k][1]==fa) continue;b[f[k][1]][0]=t,dep[f[k][1]]=dep[t]+1;
size+=dg(f[k][1],t);
if (size>=bg)
{
g++;
for (int k=1;k<=size;k++) block[sta[top--]]=g;
size=0;
}
}
sta[++top]=t;
return size+1;
}
bool cmp(node a,node b)
{
return (block[a.x]==block[b.x]?dfn[a.y]<dfn[b.y]:block[a.x]<block[b.x]);
}
int getlca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
int k=dep[x]-dep[y];
for (int i=16;i>=0;i--)
{
if (k>=mi[i]) k-=mi[i],x=b[x][i];
}
if (x==y) return x;
for (int i=16;i>=0;i--)
{
if (b[x][i]!=b[y][i]) x=b[x][i],y=b[y][i];
}
return b[x][0];
}
void work(int x)
{
if (!a[x]) now+=(++num[co[x]]==1);
else now-=(--num[co[x]]==0);
a[x]^=1;
}
void change(int x,int y)
{
while (x!=y)
{
if (dep[x]>dep[y]) work(x),x=b[x][0];
else work(y),y=b[y][0];
}
}
int main()
{
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) scanf("%d",&co[i]);
for (i=1;i<=n;i++)
{
scanf("%d%d",&o,&p);
if (!(o*p)) root=o+p;
else insert(o,p),insert(p,o);
}
bg=sqrt(n);dg(root,0);g++;
while (top) block[sta[top--]]=g;mi[0]=1;
for (i=1;i<=16;i++)
{
mi[i]=mi[i-1]*2;
for (j=1;j<=n;j++) b[j][i]=b[b[j][i-1]][i-1];
}
for (i=1;i<=m;i++) scanf("%d%d%d%d",&que[i].x,&que[i].y,&que[i].a,&que[i].b),que[i].id=i;
sort(que+1,que+m+1,cmp);
int x=root,y=root;now=0;
for (i=1;i<=m;i++)
{
if (x!=que[i].x) change(x,que[i].x),x=que[i].x;
if (y!=que[i].y) change(y,que[i].y),y=que[i].y;
k=getlca(x,y);work(k);
if ((que[i].a==que[i].b)||(!(num[que[i].a]*num[que[i].b]))) ans[que[i].id]=now;
else ans[que[i].id]=now-1;work(k);
}
for (i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}
圆方树上最短路 JZOJ1914
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int sum[400005],bh[400005],co[400005],dfn[400005],len[400005],dis[400005],sta[400005],f[500005][4],q[100005],dep[100005],bz[400005],vis[400005],b[100005][18],mi[18];
int i,j,k,m,n,o,p,l,s,T=1,x,y,z,times,tot,xx,yy;
queue<int> h;
void insert(int x,int y,int z) {f[++T][1]=y,f[T][2]=q[x],f[T][3]=z,q[x]=T;}
void read(int &x)
{
char ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
void dg(int t)
{
dfn[t]=++tot;sta[++sta[0]]=t;
for (int k=q[t];k;k=f[k][2])
{
if (vis[k]||vis[k^1]||k>2*m+1) continue;
if (!dfn[f[k][1]])
len[f[k][1]]=len[t]+f[k][3],bh[f[k][1]]=k,vis[k]=vis[k^1]=1,dg(f[k][1]);
else {
if (dfn[f[k][1]]>=dfn[t]) continue;
co[f[k][1]]=++co[0];bz[k]=bz[k^1]=1;sum[co[0]]=f[k][3];
for (int i=t;i!=f[k][1];i=f[bh[i]^1][1])
{
bz[bh[i]]=bz[bh[i]^1]=1,sum[co[0]]+=f[bh[i]^1][3];
co[i]=co[0];insert(f[k][1],i,0),insert(i,f[k][1],0);
}
}
}
}
void dfs(int t)
{
for (int k=q[t];k;k=f[k][2])
{
if (vis[k]||bz[k]) continue;
vis[k]=vis[k^1]=1;
dep[f[k][1]]=dep[t]+1;b[f[k][1]][0]=t;
dfs(f[k][1]);
}
}
int lca(int &x,int &y)
{
if (dep[x]<dep[y]) swap(x,y);
int k=dep[x]-dep[y];
for (int i=17;i>=0;i--)
if (k>=mi[i]) k-=mi[i],x=b[x][i];
if (x==y) return x;
for (int i=17;i>=0;i--)
if (b[x][i]!=b[y][i]) x=b[x][i],y=b[y][i];
return b[x][0];
}
int main()
{
freopen("garden.in","r",stdin);
freopen("garden.out","w",stdout);
read(n),read(m);
for (mi[0]=i=1;i<=17;i++) mi[i]=mi[i-1]*2;
for (i=1;i<=m;i++) read(x),read(y),read(z),insert(x,y,z),insert(y,x,z);
h.push(1);memset(dis,60,sizeof(dis));dis[1]=0;
while (!h.empty())
{
int st=h.front();h.pop();
for (k=q[st];k;k=f[k][2])
{
if (dis[st]+f[k][3]<dis[f[k][1]])
{
dis[f[k][1]]=dis[st]+f[k][3];
h.push(f[k][1]);
}
}
}
dg(1);memset(vis,0,sizeof(vis));
dfs(1);
for (i=1;i<=17;i++)
for (j=1;j<=n;j++)
b[j][i]=b[b[j][i-1]][i-1];
read(times);
while (times--)
{
read(x),read(y),xx=x,yy=y,z=lca(x,y);
if (co[x]==co[y]&&co[x])
{
s=abs(len[x]-len[y]);
printf("%d\n",dis[xx]-dis[x]+dis[yy]-dis[y]+min(s,sum[co[x]]-s));
} else printf("%d\n",dis[xx]+dis[yy]-2*dis[z]);
}
return 0;
}
主席树 JZOJ7050
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define ll long long
#define mo 998244353
#define N 100005
#define M 10000005
using namespace std;
int dep[N],f[N<<1][3],q[N],lson[M],rson[M],root[N],tree[M];
int pr[M>>3],bz[M],a[N],mn[M],c[N];
int ys[N][9],sum[N][9],len[N],id[N];
int b[N][18],mi[18];
struct node{
int val,dep;
friend bool operator <(node a,node b) {return a.dep<b.dep;}
};
set<node> g[M];
int dfn[N],size[N];
int i,j,k,m,n,o,p,l,s,t,x,y,tot,h,lastans,opt;
void read(int &x)
{
char ch=getchar();x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
void insert(int x,int y) {f[++t][1]=y,f[t][2]=q[x],q[x]=t;}
void dg(int t,int fa)
{
dep[t]=dep[fa]+1,dfn[t]=++tot,size[t]=1;
for (int k=q[t];k;k=f[k][2])
{
if (f[k][1]==fa) continue;
b[f[k][1]][0]=t;
dg(f[k][1],t);
size[t]+=size[f[k][1]];
}
}
bool cmp(int a,int b) {return dep[a]<dep[b];}
int ksm(int x,int y)
{
int ans=1;
for (;y;y>>=1,x=1ll*x*x%mo)
if (y&1) ans=1ll*ans*x%mo;
return ans;
}
int getlca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
int k=dep[x]-dep[y];
for (int i=17;i>=0;i--)
if (k>=mi[i]) k-=mi[i],x=b[x][i];
if (x==y) return x;
for (int i=17;i>=0;i--)
if (b[x][i]!=b[y][i]) x=b[x][i],y=b[y][i];
return b[x][0];
}
void change(int &x,int l,int r,int pos,int mul)
{
if (!x) x=++tot,tree[x]=1;
if (l==r) {
tree[x]=1ll*tree[x]*mul%mo;return;
}
int mid=l+r>>1;
if (pos<=mid) change(lson[x],l,mid,pos,mul);
else change(rson[x],mid+1,r,pos,mul);
tree[x]=1ll*tree[lson[x]]*tree[rson[x]]%mo;
}
int merge(int l,int r,int x,int y)
{
if (!x||!y) return x+y;
if (l==r)
{
tree[x]=1ll*tree[x]*tree[y]%mo;
return x;
}
else {
int mid=l+r>>1;
lson[x]=merge(l,mid,lson[x],lson[y]);
rson[x]=merge(mid+1,r,rson[x],rson[y]);
tree[x]=1ll*tree[lson[x]]*tree[rson[x]]%mo;
return x;
}
}
int query(int x,int l,int r,int st,int en)
{
if (l>=st&&r<=en) return tree[x];
else {
int mid=l+r>>1;
if (en<=mid) return query(lson[x],l,mid,st,en);
else if (st>mid) return query(rson[x],mid+1,r,st,en);
else return 1ll*query(lson[x],l,mid,st,mid)*query(rson[x],mid+1,r,mid+1,en)%mo;
}
}
int main()
{
freopen("half.in","r",stdin);
freopen("half.out","w",stdout);
read(opt),read(n);
for (i=mi[0]=1;i<=17;i++) mi[i]=mi[i-1]*2%mo;
for (i=1;i<=n;i++) read(a[i]),o=(a[i]>o?a[i]:o);
for (i=2;i<=o;i++)
{
if (!bz[i]) pr[++pr[0]]=i,mn[i]=i;
for (j=1;j<=pr[0]&&pr[j]*i<=o;j++)
{
bz[i*pr[j]]=1,mn[i*pr[j]]=pr[j];
if (!(i%pr[j])) break;
}
}
for (i=1;i<=n-1;i++) read(x),read(y),insert(x,y),insert(y,x);
dg(1,0);
for (i=1;i<=n;i++)
{
c[0]=0;
if (a[i]==1) continue;
for (k=a[i];k>1;k/=mn[k]) c[++c[0]]=mn[k];
sort(c+1,c+c[0]+1);
for (j=1;j<=c[0];j++)
{
if (c[j]!=ys[i][len[i]]) ys[i][++len[i]]=c[j],sum[i][len[i]]=1;
else sum[i][len[i]]++;
}
}
memset(bz,0,sizeof(bz));
for (i=1;i<=n;i++) id[i]=i;
sort(id+1,id+n+1,cmp);tot=0,j=1;
tree[0]=1;
for (i=1;i<=17;i++)
for (j=1;j<=n;j++)
b[j][i]=b[b[j][i-1]][i-1];
for (i=j=1;i<=n;i++)
{
root[i]=++tot,tree[tot]=1;
if (i==3)
{
int ddf=0;
}
while (j<=n&&dep[id[j]]<=i)
{
for (k=1;k<=len[id[j]];k++)
{
int mul=1,inv=ksm(ys[id[j]][k],mo-2);
for (l=1;l<=sum[id[j]][k];l++)
{
mul*=ys[id[j]][k];
g[mul].insert((node){id[j],dfn[id[j]]});
change(root[i],1,n,dfn[id[j]],ys[id[j]][k]);
set<node>::iterator st=g[mul].begin(),en=g[mul].end(),pos=g[mul].find((node){id[j],dfn[id[j]]});
en--;
int bz1=((*st).dep==(*pos).dep),bz2=((*en).dep==(*pos).dep);
if (!bz1) st=pos,st--,change(root[i],1,n,dfn[getlca(id[j],(*st).val)],inv);
if (!bz2) en=pos,en++,change(root[i],1,n,dfn[getlca(id[j],(*en).val)],inv);
if (!bz1&&!bz2) change(root[i],1,n,dfn[getlca((*st).val,(*en).val)],ys[id[j]][k]);
}
}
j++;
}
if (i==2)
{
int gsdfg=0;
}
merge(1,n,root[i],root[i-1]);
}
read(m);
for (i=1;i<=m;i++)
{
read(x),read(y);
x^=(opt*lastans),y^=(opt*lastans);
printf("%d\n",lastans=query(root[min(dep[id[n]],dep[x]+y)],1,n,dfn[x],dfn[x]+size[x]-1));
}
return 0;
}
Loading…