主席树

void build(int lst,int now,int l,int r,int v)
{
if(l==r)
{
tr[now].sm=tr[lst].sm+1;
return;
}
int mid=(l+r)/2,lts=tr[lst].ls,rts=tr[lst].rs;
if (v<=mid) tr[now].rs=rts,tr[now].ls=++nd,build(lts,nd,l,mid,v);
else tr[now].ls=lts,tr[now].rs=++nd,build(rts,tr[now].rs,mid+1,r,v);
tr[now].sm=tr[tr[now].ls].sm+tr[tr[now].rs].sm;
}
int find(int lst,int now,int l,int r,int v)
{
if(l==r) return l;
int mid=(l+r)/2;
int lts=tr[lst].ls,lns=tr[now].ls,sum=tr[lns].sm-tr[lts].sm;
if (sum>=v) find(lts,lns,l,mid,v);
else find(tr[lst].rs,tr[now].rs,mid+1,r,v-sum);
}

树链剖分

struct note
{
int mx,ls,rs;
}tree[2000005];
struct rd
{
int x,y;
}a[MAXN];
int top[MAXN],size[MAXN],son[MAXN],dfn[MAXN],pt[MAXN],ft[MAXN],deep[MAXN],n,m,a1[MAXN][2],df,num;
bool cmp(rd x,rd y)
{
return x.x<y.x;
}
void dfs1(int k)
{
int i,mx=0;
if (a1[k][0]!=0)
fo(i,a1[k][0],a1[k][1])
{
dfs1(a[i].y);
size[k]+=size[a[i].y];
if (size[a[i].y]>mx)
{
son[k]=a[i].y;
mx=size[a[i].y];
}
}
size[k]++;
}
void dfs2(int k)
{
int i;
dfn[k]=++df;
pt[df]=k;
if (son[k]!=0)
{
top[son[k]]=top[k];
dfs2(son[k]);
}
if (a1[k][0]!=0)
fo(i,a1[k][0],a1[k][1])
{
if(a[i].y==son[k]) continue;
top[a[i].y]=a[i].y;
dfs2(a[i].y);
}
}
int find(int now,int l,int r,int x,int y)
{
if (now==0) return 0;
int ls=tree[now].ls,rs=tree[now].rs;
if (l==x&&r==y) return tree[now].mx;
int mid=(l+r)/2;
if (y<=mid) return find(ls,l,mid,x,y);
else if(x>mid) return find(rs,mid+1,r,x,y);
else return max(find(ls,l,mid,x,mid),find(rs,mid+1,r,mid+1,y));
}
void change(int now,int l,int r,int x,int y,int v)
{
int ls=tree[now].ls,rs=tree[now].rs;
if (l==x&&r==y)
{
tree[now].mx=v;
return;
}
int mid=(l+r)/2;
if (ls==0) ls=tree[now].ls=++num,tree[ls].mx=0;
if (rs==0) rs=tree[now].rs=++num,tree[rs].mx=0;
if (y<=mid) change(ls,l,mid,x,y,v);
else if(x>=mid) change(rs,mid+1,r,x,y,v);
else change(ls,l,mid,x,mid,v),change(rs,mid+1,r,mid+1,y,v);
tree[now].mx=max(tree[ls].mx,tree[rs].mx);
}
int ask(int x,int y)
{
int fx=top[x],fy=top[y];
if (fx==fy)
{
if (deep[x]>deep[y]) swap(x,y);
return find(1,1,n,dfn[x],dfn[y]);
}
else
{
if (deep[fx]<deep[fy]) swap(fx,fy),swap(x,y);
return max(find(1,1,n,dfn[fx],dfn[x]),ask(ft[fx],y));
}
}

SA

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
int n,m;
int SA[100001],rank[100001],ct[100001],s2[100001],r1[100001],height[100001];
char st[100001];
void findh()
{
height[1]=0;
int i=0,j;
fo(i,1,n)
{
if (rank[i]==1) continue;
j=max(height[rank[i-1]]-1,0);
while (st[i+j]==st[SA[rank[i]-1]+j]) j++;
height[rank[i]]=j;
}
}
void make()
{
memset(ct,0,sizeof(ct));
int i,j,k,mx;
fo(i,1,n) ct[rank[i]=st[i]]++;
fo(i,1,m) ct[i]+=ct[i-1];
fod(i,n,1) SA[ct[rank[i]]--]=i;
mx=m;
for(j=1,k=0;k<n;j*=2,mx=k)
{
int p=0;
fo(i,n-j+1,n) s2[++p]=i;
fo(i,1,n) if(SA[i]>j) s2[++p]=SA[i]-j;
memset(ct,0,sizeof(ct));
fo(i,1,n) ct[rank[s2[i]]]++;
fo(i,1,mx) ct[i]+=ct[i-1];
fod(i,n,1) SA[ct[rank[s2[i]]]--]=s2[i];
r1[SA[1]]=k=1;
fo(i,2,n) r1[SA[i]]=(rank[SA[i-1]]==rank[SA[i]]&&rank[SA[i-1]+j]==rank[SA[i]+j])?k:++k;
fo(i,1,n) rank[i]=r1[i];
}
}
int main()
{
freopen("SA.in","r",stdin);
scanf("%s",st+1);
n=strlen(st+1);
int i;
fo(i,1,n)
{
int cm=st[i];
m=max(m,cm);
}
make();
fo(i,1,n) printf("%d ",SA[i]);
cout<<endl;
findh();
fo(i,2,n) printf("%d ",height[i]);
}

莫比乌斯反演

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
long long mu[50005];
int a,b,c,d,k;
int prime[50005],n;
bool bz[50005];
void getprime(int lim)
{
int i,j,num=0;
fo(i,2,lim)
{
if (!bz[i])
{
prime[++num]=i;
mu[i]=-1;
}
for(j=1;i*prime[j]<=lim&&j<=num;j++)
{
if (i*prime[j]>50000) break;
bz[i*prime[j]]=1;
if (prime[j]==i) break;
if (!(i%prime[j]))
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}
int find(int k,int mx,int my)
{
int i=1,j;
long long ans=0;
while(i<=trunc(min(mx,my)/k))
{
j=min(mx/(mx/i),my/(my/i));
ans+=trunc(my/(i*k))*trunc(mx/(i*k))*(mu[j]-mu[i-1]);
i=j+1;
}
return (int)ans;
}
int main()
{
freopen("inversion.in","r",stdin);
getprime(50000);
scanf("%d",&n);
mu[1]=1;
int i;
fo(i,2,50000) mu[i]+=mu[i-1];
while(n-->0)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
printf("%d\n",(int)(find(k,b,d)-find(k,a-1,d)-find(k,b,c-1)+find(k,a-1,c-1)));
}
}