字符串
- AC自动机
- manacher
【APIO2014】uoj103 Palindromes【2017.7.12】
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=600010;
#define LL long long
char s[maxn];
int trans[maxn][30],fail[maxn],val[maxn],cnt[maxn],ord[maxn],mxl[maxn],num[maxn],fa[maxn][20],pos[maxn],n,tot=1;
int main()
{
//int xxx=0;
//freopen("b.in","r",stdin);
//freopen("b.out","w",stdout);
LL ans=0;
int last=1,u,nu,v,nv,x,y,lim=0,mx,id;
scanf("%s",s+1);
n=strlen(s+1);
for (int i=1;i<=n;i++)
{
x=s[i]-'a'+1;
u=last;
val[last=nu=++tot]=i;
while (u&&!trans[u][x])
{
trans[u][x]=nu;
u=fail[u];
}
if (!u) fail[nu]=1;
else
{
v=trans[u][x];
if (val[v]==val[u]+1) fail[nu]=v;
else
{
val[nv=++tot]=val[u]+1;
fail[nv]=fail[v];
fail[v]=fail[nu]=nv;
for (int j=1;j<=26;j++) trans[nv][j]=trans[v][j];
while (u&&trans[u][x]==v)
{
trans[u][x]=nv;
u=fail[u];
}
}
}
}
pos[0]=1;
for (int i=1;i<=n;i++) num[pos[i]=trans[pos[i-1]][s[i]-'a'+1]]++;
for (int i=1;i<=tot;i++) cnt[val[i]]++;
for (int i=1;i<=n;i++) cnt[i]+=cnt[i-1];
for (int i=1;i<=tot;i++) ord[cnt[val[i]]--]=i;
for (int i=tot;i>=1;i--) num[fail[ord[i]]]+=num[ord[i]];
while ((1<<lim)<tot) lim++;
for (int i=1;i<=tot;i++) fa[i][0]=fail[i];
for (int k=1;k<=lim;k++)
for (int i=1;i<=tot;i++)
fa[i][k]=fa[fa[i][k-1]][k-1];
for (int i=n*2+1;i>=1;i--) s[i]=(i&1)?'$':s[i/2];
s[0]='@';
s[2*n+2]='%';
mx=0;
for (int i=1;i<=2*n+1;i++)
{
if (i<=mx) mxl[i]=min(mxl[2*id-i],mx-i);
//printf("%d:%d,%d,%d\n",i,id,mx,mxl[i]);
while (s[i-mxl[i]-1]==s[i+mxl[i]+1])
{
mxl[i]++;
//xxx++;
}
if (i+mxl[i]>mx)
{
for (int j=mx;j<=i+mxl[i];j+=2)
{
x=j/2;
y=(2*i-j)/2+1;
u=pos[x];
for (int k=lim;k>=0;k--)
if (val[fa[u][k]]>=x-y+1) u=fa[u][k];
ans=max(ans,(LL)num[u]*(x-y+1));
}
mx=i+mxl[i];
id=i;
}
}
//printf("%d\n",xxx);
printf("%lld\n",ans);
}
- 后缀数组
poj1743 Musical Theme【2017.4.21】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int c=90,maxn=30010,oo=0x3f3f3f3f;
int a[maxn],sa[maxn],rank[maxn],height[maxn],f[maxn],cnt[maxn],n;
void solve()
{
int m,p,l,r,mid,ok,mnp,mxp;
memset(a,0,sizeof(a));
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<n;i++) a[i]=a[i+1]-a[i]+c;
a[n]=0;
m=190;
for (int i=1;i<=m;i++) cnt[i]=0;
for (int i=1;i<n;i++) cnt[rank[i]=a[i]]++;
for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for (int i=n-1;i;i--) sa[cnt[a[i]]--]=i;
for (int k=1;k<n;k<<=1)
{
p=0;
for (int i=n-k;i<n;i++) f[++p]=i;
for (int i=1;i<n;i++) if (sa[i]-k>=1) f[++p]=sa[i]-k;
for (int i=1;i<=m;i++) cnt[i]=0;
for (int i=1;i<n;i++) cnt[rank[f[i]]]++;
for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for (int i=n-1;i;i--) sa[cnt[rank[f[i]]]--]=f[i];
for (int i=1;i<n;i++) f[i]=rank[i];
rank[sa[1]]=1;
for (int i=2;i<n;i++)
if (f[sa[i]]!=f[sa[i-1]]||f[sa[i]+k]!=f[sa[i-1]+k])
rank[sa[i]]=rank[sa[i-1]]+1;
else
rank[sa[i]]=rank[sa[i-1]];
m=rank[sa[n-1]];
if (m>=n-1) break;
}
for (int i=1;i<n;i++)
{
height[rank[i]]=height[rank[i-1]];
if (height[rank[i]]) height[rank[i]]--;
while (a[i+height[rank[i]]]==a[sa[rank[i]-1]+height[rank[i]]]) height[rank[i]]++;
}
l=0;
r=n-1;
while (l<r)
{
mid=l+r+1>>1;
ok=0;
for (int i=1;i<n&&!ok;i++)
if (height[i]>=mid)
{
mxp=max(mxp,sa[i]);
mnp=min(mnp,sa[i]);
if (mxp-mnp>mid) ok=1;
}
else mxp=mnp=sa[i];
if (ok) l=mid;
else r=mid-1;
}
//printf("%d\n",l+1);
if (l>=4) printf("%d\n",l+1);
else printf("0\n");
}
int main()
{
while (scanf("%d",&n)&&n) solve();
}
poj2774 Long Long Message【2017.5.17】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=400010;
char s[maxn];
int sa[maxn],rank[maxn],height[maxn],f[maxn],g[maxn],cnt[maxn];
int main()
{
int n,m=27,l,p,ans=0;
scanf("%s",s+1);
l=strlen(s+1);
s[l+1]='z'+1;
scanf("%s",s+l+2);
n=strlen(s+1);
for (int i=1;i<=n;i++) cnt[rank[i]=s[i]-'a'+1]++;
for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for (int i=n;i;i--) sa[cnt[rank[i]]--]=i;
for (int k=1;;k<<=1)
{
p=0;
for (int i=n-k+1;i<=n;i++) f[++p]=i;
for (int i=1;i<=n;i++)
if (sa[i]>k) f[++p]=sa[i]-k;
for (int i=1;i<=m;i++) cnt[i]=0;
for (int i=1;i<=n;i++) cnt[rank[f[i]]]++;
for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for (int i=n;i;i--) sa[cnt[rank[f[i]]]--]=f[i];
for (int i=1;i<=n;i++) g[i]=rank[i];
rank[sa[1]]=1;
for (int i=2;i<=n;i++)
rank[sa[i]]=rank[sa[i-1]]+(g[sa[i]]!=g[sa[i-1]]||g[sa[i]+k]!=g[sa[i-1]+k]);
m=rank[sa[n]];
if (m>=n) break;
}
for (int i=1;i<=n;i++)
{
height[rank[i]]=height[rank[i-1]];
if (height[rank[i]]) height[rank[i]]--;
while (s[i+height[rank[i]]]==s[sa[rank[i]-1]+height[rank[i]]]) height[rank[i]]++;
}
for (int i=2;i<=n;i++)
if ((sa[i]<=l&&sa[i-1]>=l+2)||(sa[i]>=l+2&&sa[i-1]<=l))
ans=max(ans,height[i]);
printf("%d\n",ans);
}
- 后缀自动机
SPOJ NSUBSTR Substrings【2017.4.21】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500010;
char s[maxn];
int fail[maxn],val[maxn],trans[maxn][30],cnt[maxn],f[maxn],num[maxn],ans[maxn],
n,tot=1;
int main()
{
int p,last=1,x,np,q,nq;
scanf("%s",s+1);
n=strlen(s+1);
for (int i=1;i<=n;i++)
{
x=s[i]-'a';
p=last;
val[last=np=++tot]=val[p]+1;
while (p&&!trans[p][x])
{
trans[p][x]=np;
p=fail[p];
}
if (!p) fail[np]=1;
else
{
q=trans[p][x];
if (val[q]==val[p]+1) fail[np]=q;
else
{
val[nq=++tot]=val[p]+1;
fail[nq]=fail[q];
fail[q]=fail[np]=nq;
for (int j=0;j<26;j++) trans[nq][j]=trans[q][j];
while (p&&trans[p][x]==q)
{
trans[p][x]=nq;
p=fail[p];
}
}
}
}
p=1;
for (int i=1;i<=n;i++)
{
p=trans[p][s[i]-'a'];
cnt[p]++;
}
for (int i=1;i<=tot;i++) num[val[i]]++;
for (int i=n-1;i;i--) num[i]+=num[i+1];
for (int i=1;i<=tot;i++) f[num[val[i]]--]=i;
for (int i=1;i<=tot;i++)
{
cnt[fail[f[i]]]+=cnt[f[i]];
ans[val[f[i]]]=max(ans[val[f[i]]],cnt[f[i]]);
}
for (int i=n-1;i;i--) ans[i]=max(ans[i],ans[i+1]);
for (int i=1;i<=n;i++) printf("%d\n",ans[i]);
}
poj2774 Long Long Message【2017.5.17】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200010;
char s1[maxn],s2[maxn];
int trans[maxn][30],fail[maxn],val[maxn],
n,m,tot=1;
int main()
{
int last=1,x,p,q,np,nq,now=0,ans=0;
scanf("%s",s1+1);
n=strlen(s1+1);
for (int i=1;i<=n;i++)
{
x=s1[i]-'a'+1;
p=last;
val[last=np=++tot]=val[p]+1;
while (p&&!trans[p][x])
{
trans[p][x]=np;
p=fail[p];
}
if (!p) fail[np]=1;
else
{
q=trans[p][x];
if (val[q]==val[p]+1) fail[np]=q;
else
{
val[nq=++tot]=val[p]+1;
fail[nq]=fail[q];
fail[q]=fail[np]=nq;
for (int j=1;j<=26;j++) trans[nq][j]=trans[q][j];
while (p&&trans[p][x]==q)
{
trans[p][x]=nq;
p=fail[p];
}
}
}
}
scanf("%s",s2+1);
m=strlen(s2+1);
p=1;
for (int i=1;i<=m;i++)
{
x=s2[i]-'a'+1;
if (trans[p][x])
{
p=trans[p][x];
now++;
}
else
{
while (p&&!trans[p][x]) p=fail[p];
if (p)
{
now=val[p]+1;
p=trans[p][x];
}
else
{
now=0;
p=1;
}
}
ans=max(ans,now);
}
printf("%d\n",ans);
}
- 回文自动机
【APIO2014】bzoj3676 回文串
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=600010;
char s[maxn];
int val[maxn],fail[maxn],trans[maxn][30],cnt[maxn],num[maxn],f[maxn],n;
int main()
{
int tot=1,last=0,p,np,x,q;
LL ans=0;
scanf("%s",s+1);
n=strlen(s+1);
fail[0]=fail[1]=1;
val[1]=-1;
for (int i=1;i<=n;i++)
{
x=s[i]-'a';
p=last;
while (s[i-val[p]-1]!=s[i]) p=fail[p];
if (!trans[p][x])
{
val[np=++tot]=val[p]+2;
q=fail[p];
while (s[i-val[q]-1]!=s[i]) q=fail[q];
fail[np]=trans[q][x];
trans[p][x]=np;
}
cnt[last=trans[p][x]]++;
}
for (int i=2;i<=tot;i++) num[val[i]]++;
for (int i=1;i<=n;i++) num[i]+=num[i-1];
for (int i=2;i<=tot;i++) f[num[val[i]]--]=i;
for (int i=tot-1;i;i--)
{
ans=max(ans,(LL)val[f[i]]*cnt[f[i]]);
cnt[fail[f[i]]]+=cnt[f[i]];
}
printf("%lld\n",ans);
}
树形数据结构
- treap
bzoj3224 普通平衡树【2017.4.17】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010,no=2e9+100;
int rd()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
struct treap
{
int son[2][maxn],v[maxn],w[maxn],siz[maxn],cnt[maxn],rt,tot;
void upd(int p)
{
siz[p]=siz[son[0][p]]+siz[son[1][p]]+cnt[p];
}
void rot(int &p,int fl)
{
int u=son[fl][p],v=son[fl^1][u];
son[fl][p]=v;
son[fl^1][u]=p;
upd(p);
p=u;
upd(p);
}
void ins(int &p,int x)
{
if (!p)
{
p=++tot;
v[p]=x;
w[p]=rand();
siz[p]=cnt[p]=1;
return;
}
siz[p]++;
if (v[p]==x)
{
cnt[p]++;
return;
}
int flag=x>v[p];
ins(son[flag][p],x);
if (w[son[flag][p]]>w[p]) rot(p,flag);
}
void del(int &p,int x)
{
if (v[p]==x)
{
if (son[0][p]*son[1][p]==0)
{
cnt[p]--;
siz[p]--;
if (!cnt[p]) p=son[0][p]+son[1][p];
}
else
{
int fl=w[son[0][p]]<w[son[1][p]];
rot(p,fl);
siz[p]--;
del(son[fl^1][p],x);
}
return;
}
siz[p]--;
del(son[x>v[p]][p],x);
}
int rank(int p,int x)
{
if (v[p]==x) return siz[son[0][p]]+1;
if (x<v[p]) return rank(son[0][p],x);
return siz[son[0][p]]+cnt[p]+rank(son[1][p],x);
}
int qry(int p,int x)
{
if (x<=siz[son[0][p]]) return qry(son[0][p],x);
if (x<=siz[son[0][p]]+cnt[p]) return v[p];
return qry(son[1][p],x-(siz[son[0][p]]+cnt[p]));
}
int pre(int p,int x)
{
if (!p) return no;
if (v[p]<x)
{
int y=pre(son[1][p],x);
return y==no?v[p]:y;
}
return pre(son[0][p],x);
}
int suc(int p,int x)
{
if (!p) return no;
if (v[p]>x)
{
int y=suc(son[0][p],x);
return y==no?v[p]:y;
}
return suc(son[1][p],x);
}
void Ins(int x)
{
ins(rt,x);
}
void Del(int x)
{
del(rt,x);
}
int Rank(int x)
{
return rank(rt,x);
}
int Qry(int x)
{
return qry(rt,x);
}
int Pre(int x)
{
return pre(rt,x);
}
int Suc(int x)
{
return suc(rt,x);
}
}t;
int main()
{
int n,opt;
n=rd();
while (n--)
{
opt=rd();
switch (opt)
{
case 1:t.Ins(rd());break;
case 2:t.Del(rd());break;
case 3:printf("%d\n",t.Rank(rd()));break;
case 4:printf("%d\n",t.Qry(rd()));break;
case 5:printf("%d\n",t.Pre(rd()));break;
case 6:printf("%d\n",t.Suc(rd()));break;
}
}
}
- splay
bzoj3224 普通平衡树【2017.4.17】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010,no=2e9+1000;
int rd()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int fa[maxn],son[maxn][2],v[maxn],cnt[maxn],siz[maxn],
tot,rt;
void pause()
{
int x=0;
x=1;
}
void upd(int p)
{
siz[p]=siz[son[p][0]]+siz[son[p][1]]+cnt[p];
}
void rot(int p,int fl)
{
int u=son[p][fl],v=son[u][fl^1];
fa[u]=fa[p];
if (!fa[u]) rt=u;
else son[fa[u]][son[fa[u]][1]==p]=u;
son[p][fl]=v;
if (v) fa[v]=p;
son[u][fl^1]=p;
fa[p]=u;
upd(p);
upd(u);
}
void splay(int u)
{
int v,x,w,y;
upd(u);
while (rt!=u)
{
v=fa[u];
x=son[v][1]==u;
if (v==rt) rot(v,x);
else
{
w=fa[v];
y=son[w][1]==v;
if (x==y) rot(w,y),rot(v,x);
else rot(v,x),rot(w,y);
}
}
}
void ins(int p,int x,int f,int fl)
{
if (!p)
{
p=++tot;
cnt[p]=1;
v[p]=x;
if (f)
{
fa[p]=f;
son[f][fl]=p;
}
else rt=p;
splay(p);
return;
}
if (x==v[p])
{
cnt[p]++;
splay(p);
return;
}
int fl2=x>v[p];
ins(son[p][fl2],x,p,fl2);
}
void del(int p,int x,int f,int fl)
{
if (v[p]==x)
{
if (cnt[p]>1)
{
cnt[p]--;
splay(p);
}
else
{
if (son[p][0]*son[p][1]==0)
{
if (f)
{
son[f][fl]=son[p][0]+son[p][1];
if (son[f][fl])
{
fa[son[f][fl]]=f;
splay(son[f][fl]);
}
else splay(f);
}
else fa[rt=son[p][0]+son[p][1]]=0;
}
else
{
int fl2=siz[son[p][0]]<siz[son[p][1]];
rot(p,fl2);
del(p,x,fa[p],fl2^1);
}
}
}
else
{
int fl2=x>v[p];
del(son[p][fl2],x,p,fl2);
}
}
int rank(int p,int x)
{
if (x==v[p])
{
splay(p);
return siz[son[p][0]]+1;
}
if (x<v[p]) return rank(son[p][0],x);
return rank(son[p][1],x);
}
int qry(int p,int x)
{
if (x<=siz[son[p][0]]) return qry(son[p][0],x);
if (x<=siz[son[p][0]]+cnt[p])
{
splay(p);
return v[p];
}
return qry(son[p][1],x-siz[son[p][0]]-cnt[p]);
}
int pre(int p,int x)
{
if (!p) return no;
if (v[p]<x)
{
int y=pre(son[p][1],x);
if (y==no)
{
splay(p);
return v[p];
}
return y;
}
return pre(son[p][0],x);
}
int suc(int p,int x)
{
if (!p) return no;
if (v[p]>x)
{
int y=suc(son[p][0],x);
if (y==no)
{
splay(p);
return v[p];
}
return y;
}
return suc(son[p][1],x);
}
int main()
{
/*freopen("phs.in","r",stdin);
freopen("phs.out","w",stdout);*/
int n,opt;
n=rd();
while (n--)
{
if (n==1) pause();
opt=rd();
switch (opt)
{
case 1:ins(rt,rd(),0,0);break;
case 2:del(rt,rd(),0,0);break;
case 3:printf("%d\n",rank(rt,rd()));break;
case 4:printf("%d\n",qry(rt,rd()));break;
case 5:printf("%d\n",pre(rt,rd()));break;
case 6:printf("%d\n",suc(rt,rd()));break;
}
}
}
【AHOI2006】bzoj1269 文本编辑器【2017.4.19】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define rt son[1][0]
const int maxn=4000010;
char s[maxn],s1[maxn],chr[maxn];
int fa[maxn],son[maxn][2],inv[maxn],size[maxn],tot=3;
void down(int u)
{
if (inv[u])
{
swap(son[u][0],son[u][1]);
if (son[u][0]) inv[son[u][0]]^=1;
if (son[u][1]) inv[son[u][1]]^=1;
inv[u]=0;
}
}
void upd(int u)
{
size[u]=size[son[u][0]]+size[son[u][1]]+1;
}
int find(int u,int p)
{
down(u);
if (p<=size[son[u][0]]) return find(son[u][0],p);
if (p==size[son[u][0]]+1) return u;
return find(son[u][1],p-size[son[u][0]]-1);
}
void rot(int u,int f)
{
int v=son[u][f],w=son[v][f^1],x=fa[u],fx=son[x][1]==u;
son[u][f]=w;
if (w) fa[w]=u;
son[v][f^1]=u;
fa[u]=v;
son[x][fx]=v;
fa[v]=x;
upd(u);
upd(v);
}
void get(int p,int f)
{
int u=find(rt,p),x,y,fx,fy;
while (fa[u]!=f)
{
x=fa[u];
fx=son[x][1]==u;
y=fa[x];
fy=son[y][1]==x;
if (y==f) rot(x,fx);
else
{
if (fx==fy) rot(y,fy),rot(x,fx);
else rot(x,fx),rot(y,fy);
}
}
}
int build(int l,int r)
{
if (l>r) return 0;
int mid=l+r>>1,ret;
chr[ret=++tot]=s[mid];
son[ret][0]=build(l,mid-1);
if (son[ret][0]) fa[son[ret][0]]=ret;
son[ret][1]=build(mid+1,r);
if (son[ret][1]) fa[son[ret][1]]=ret;
upd(ret);
return ret;
}
int main()
{
int m,n,p=1;
scanf("%d",&m);
son[1][0]=2;
son[2][0]=3;
fa[2]=1;
fa[3]=2;
size[2]=2;
size[3]=1;
while (m--)
{
scanf("%s",s1);
switch (s1[0])
{
case 'M':scanf("%d",&p);p++;break;
case 'I':
scanf("%d",&n);
gets(s+1);
gets(s+1);
get(p,1);
get(p+1,rt);
son[son[rt][1]][0]=build(1,n);
fa[son[son[rt][1]][0]]=son[rt][1];
upd(son[rt][1]);
upd(rt);
break;
case 'D':
scanf("%d",&n);
get(p,1);
get(p+n+1,rt);
son[son[rt][1]][0]=0;
upd(son[rt][1]);
upd(rt);
break;
case 'R':
scanf("%d",&n);
get(p,1);
get(p+n+1,rt);
inv[son[son[rt][1]][0]]^=1;
break;
case 'G':
get(p+1,1);
printf("%c\n",chr[rt]);
break;
case 'P':p--;break;
case 'N':p++;break;
}
}
}
- 替罪羊树
- kdtree
bzoj2648 SJY摆棋子【2017.4.21】
#include<cstdio>
#include<algorithm>
using namespace std;
#define R(k) for (int k=0;k<2;k++)
const int maxn=2000010,oo=0x3f3f3f3f;
int D,ans;
struct Point
{
int x[2];
void rd()
{
R(k) scanf("%d",&x[k]);
}
bool operator < (const Point &p) const
{
return x[D]<p.x[D];
}
}a[maxn],p;
int lson[maxn],rson[maxn],mx[maxn][2],mn[maxn][2],tot,rt;
void upd(int p)
{
R(k)
{
mx[p][k]=mn[p][k]=a[p].x[k];
if (lson[p])
{
mx[p][k]=max(mx[p][k],mx[lson[p]][k]);
mn[p][k]=min(mn[p][k],mn[lson[p]][k]);
}
if (rson[p])
{
mx[p][k]=max(mx[p][k],mx[rson[p]][k]);
mn[p][k]=min(mn[p][k],mn[rson[p]][k]);
}
}
}
int build(int L,int R,int d)
{
if (L>R) return 0;
int mid=L+R>>1;
D=d;
nth_element(a+L,a+mid,a+R+1);
lson[mid]=build(L,mid-1,d^1);
rson[mid]=build(mid+1,R,d^1);
upd(mid);
return mid;
}
void ins(int &u,int d)
{
if (!u)
{
a[u=++tot]=p;
R(k) mn[u][k]=mx[u][k]=p.x[k];
return;
}
if (p.x[d]<a[u].x[d]) ins(lson[u],d^1);
else ins(rson[u],d^1);
upd(u);
}
int mindis(int u)
{
if (!u) return oo;
int ret=0;
R(k)
{
if (mn[u][k]>p.x[k]) ret+=mn[u][k]-p.x[k];
if (mx[u][k]<p.x[k]) ret+=p.x[k]-mx[u][k];
}
return ret;
}
void qry(int u,int d)
{
int ret=0,lmn=mindis(lson[u]),rmn=mindis(rson[u]);
R(k) ret+=abs(p.x[k]-a[u].x[k]);
ans=min(ans,ret);
if (lmn<rmn)
{
if (lmn<ans) qry(lson[u],d^1);
if (rmn<ans) qry(rson[u],d^1);
}
else
{
if (rmn<ans) qry(rson[u],d^1);
if (lmn<ans) qry(lson[u],d^1);
}
}
int main()
{
int n,m,opt;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) a[i].rd();
rt=build(1,n,0);
tot=n;
while (m--)
{
scanf("%d",&opt);
R(k) scanf("%d",&p.x[k]);
if (opt==1) ins(rt,0);
else
{
ans=oo;
qry(rt,0);
printf("%d\n",ans);
}
}
}
- 左偏树
- 主席树
poj2104 K-th Number【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2000010;
int rd()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int a[maxn],ord[maxn],rt[maxn],sum[maxn],lson[maxn],rson[maxn],n,tot;
int modi(int bro,int L,int R,int x)
{
int u=++tot;
sum[tot]=sum[bro]+1;
if (L==R) return u;
int mid=(L+R)/2;
if (x<=mid)
{
lson[u]=modi(lson[bro],L,mid,x);
rson[u]=rson[bro];
}
else
{
lson[u]=lson[bro];
rson[u]=modi(rson[bro],mid+1,R,x);
}
return u;
}
int qry(int u,int v,int L,int R,int k)
{
if (L==R) return L;
int mid=(L+R)/2;
if (k<=sum[lson[u]]-sum[lson[v]]) return qry(lson[u],lson[v],L,mid,k);
return qry(rson[u],rson[v],mid+1,R,k-(sum[lson[u]]-sum[lson[v]]));
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int m,q,l,r,k;
n=rd();
q=rd();
for (int i=1;i<=n;i++) ord[i]=a[i]=rd();
sort(ord+1,ord+n+1);
m=unique(ord+1,ord+n+1)-ord-1;
for (int i=1;i<=n;i++) a[i]=lower_bound(ord+1,ord+m+1,a[i])-ord;
for (int i=1;i<=n;i++) rt[i]=modi(rt[i-1],1,m,a[i]);
while (q--)
{
l=rd();
r=rd();
k=rd();
printf("%d\n",ord[qry(rt[r],rt[l-1],1,m,k)]);
}
}
数论
- 中国剩余定理
- 离散对数
bzoj4128 Matrix【2017.5.18】
#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define LL unsigned long long
const int maxn=75,r=131;
int n,p,m;
map<LL,int> mp;
int inc(int x,int y)
{
x+=y;return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;return x<0?x+p:x;
}
int inverse(int x)
{
int ret=1;
for (int k=p-2;k;k>>=1,x=x*x%p)
if (k&1) ret=ret*x%p;
return ret;
}
struct mat
{
int a[maxn][maxn];
LL h;
void get()
{
h=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
h=h*r+a[i][j];
}
void rd()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
get();
}
void init()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a[i][j]=(i==j);
get();
}
mat operator * (const mat &m) const
{
mat ret;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
ret.a[i][j]=0;
for (int k=1;k<=n;k++)
ret.a[i][j]=inc(ret.a[i][j],a[i][k]*m.a[k][j]%p);
}
ret.get();
return ret;
}
mat inv()
{
mat ret;
int x,t;
ret.init();
for (int i=1;i<=n;i++)
{
x=0;
for (int j=i;j<=n;j++)
if (a[j][i])
{
x=j;
break;
}
if (x!=i)
for (int j=1;j<=n;j++)
{
swap(a[i][j],a[x][j]);
swap(ret.a[i][j],ret.a[x][j]);
}
t=inverse(a[i][i]);
for (int j=1;j<=n;j++)
{
a[i][j]=a[i][j]*t%p;
ret.a[i][j]=ret.a[i][j]*t%p;
}
for (int j=1;j<=n;j++)
if (j!=i)
{
t=a[j][i];
for (int k=1;k<=n;k++)
{
a[j][k]=dec(a[j][k],a[i][k]*t%p);
ret.a[j][k]=dec(ret.a[j][k],ret.a[i][k]*t%p);
}
}
}
ret.get();
return ret;
}
}a,b,c;
int main()
{
scanf("%d%d",&n,&p);
a.rd();
b.rd();
m=sqrt(p);
c.init();
for (int i=0;i<m;i++)
{
if (!mp.count(c.h)) mp[c.h]=i;
c=c*a;
if (b.h==c.h)
{
printf("%d\n",i+1);
return 0;
}
}
c=c.inv();
for (int i=1;;i++)
{
b=b*c;
if (mp.count(b.h))
{
printf("%d\n",i*m+mp[b.h]);
return 0;
}
}
}
- 杜教筛
bzoj3944 Sum【2017.7.14】
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=2000000,p=2333333;
int prm[maxn+5],fir[p+5],ne[p+5],val[p+5],tot,num;
LL phi[maxn+5],mu[maxn+5],ansphi[p+5],ansmu[p+5];
int find(int n,LL &resphi,LL &resmu)
{
for (int i=fir[n%p];i;i=ne[i])
if (val[i]==n)
{
resphi=ansphi[i];
resmu=ansmu[i];
return 1;
}
return 0;
}
void ins(int n,LL resphi,LL resmu)
{
if (tot>p) return;
int x=n%p;
tot++;
ne[tot]=fir[x];
fir[x]=tot;
val[tot]=n;
ansphi[tot]=resphi;
ansmu[tot]=resmu;
}
void solve(int n,LL &resphi,LL &resmu)
{
if (n<=maxn)
{
resphi=phi[n];
resmu=mu[n];
return;
}
if (find(n,resphi,resmu)) return;
LL tphi,tmu;
resphi=n*(n+1LL)/2;
resmu=1;
for (unsigned int i=2,j;i<=n;i=j+1)
{
j=n/(n/i);
solve(n/i,tphi,tmu);
resphi-=(j-i+1)*tphi;
resmu-=(j-i+1)*tmu;
}
ins(n,resphi,resmu);
}
int main()
{
//freopen("a.in","r",stdin);
int n;
LL resphi,resmu;
mu[1]=phi[1]=1;
for (int i=2;i<=maxn;i++)
{
if (!phi[i])
{
prm[++num]=i;
phi[i]=i-1;
mu[i]=-1;
}
for (int j=1;j<=num&&(LL)i*prm[j]<=maxn;j++)
if (i%prm[j])
{
mu[i*prm[j]]=-mu[i];
phi[i*prm[j]]=phi[i]*(prm[j]-1);
}
else
{
mu[i*prm[j]]=0;
phi[i*prm[j]]=phi[i]*prm[j];
break;
}
phi[i]+=phi[i-1];
mu[i]+=mu[i-1];
}
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
solve(n,resphi,resmu);
printf("%lld %lld\n",resphi,resmu);
}
}
bzoj4916神犇和蒟蒻【2017.7.15】
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int p=1000000007,maxn=1000000,mod=2333333;
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;
return x<0?x+p:x;
}
int prm[maxn+10],phi[maxn+10],fir[mod+10],ne[mod+10],val[mod+10],ans[mod+10],tot,num;
int sum1(int n)
{
return (LL)n*(n+1)/2%p;
}
int sum2(int n)
{
int x=n,y=n+1,z=2*n+1;
if (x%2==0) x/=2;
else y/=2;
if (x%3==0) x/=3;
else if (y%3==0) y/=3;
else z/=3;
return (LL)x*y%p*z%p;
}
int find(int n,int &ret)
{
for (int i=fir[n%mod];i;i=ne[i])
if (val[i]==n)
{
ret=ans[i];
return 1;
}
return 0;
}
void ins(int n,int ret)
{
if (tot>mod) return;
int x=n%mod;
tot++;
ne[tot]=fir[x];
fir[x]=tot;
val[tot]=n;
ans[tot]=ret;
}
int solve(int n)
{
if (n<=maxn) return phi[n];
int ret;
if (find(n,ret)) return ret;
ret=sum2(n);
for (int i=2,j;i<=n;i=j+1)
{
j=n/(n/i);
ret=dec(ret,(LL)dec(sum1(j),sum1(i-1))*solve(n/i)%p);
}
ins(n,ret);
return ret;
}
int main()
{
phi[1]=1;
for (int i=2;i<=maxn;i++)
{
if (!phi[i])
{
prm[++num]=i;
phi[i]=i-1;
}
for (int j=1;j<=num&&(LL)i*prm[j]<=maxn;j++)
if (i%prm[j]) phi[i*prm[j]]=phi[i]*(prm[j]-1);
else
{
phi[i*prm[j]]=phi[i]*prm[j];
break;
}
phi[i]=inc(phi[i-1],(LL)i*phi[i]%p);
}
int n;
scanf("%d",&n);
printf("1\n%d\n",solve(n));
}
高等数学
- 矩阵求逆
bzoj4128 Matrix【2017.5.18】
#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
#define LL unsigned long long
const int maxn=75,r=131;
int n,p,m;
map<LL,int> mp;
int inc(int x,int y)
{
x+=y;return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;return x<0?x+p:x;
}
int inverse(int x)
{
int ret=1;
for (int k=p-2;k;k>>=1,x=x*x%p)
if (k&1) ret=ret*x%p;
return ret;
}
struct mat
{
int a[maxn][maxn];
LL h;
void get()
{
h=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
h=h*r+a[i][j];
}
void rd()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
get();
}
void init()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a[i][j]=(i==j);
get();
}
mat operator * (const mat &m) const
{
mat ret;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
ret.a[i][j]=0;
for (int k=1;k<=n;k++)
ret.a[i][j]=inc(ret.a[i][j],a[i][k]*m.a[k][j]%p);
}
ret.get();
return ret;
}
mat inv()
{
mat ret;
int x,t;
ret.init();
for (int i=1;i<=n;i++)
{
x=0;
for (int j=i;j<=n;j++)
if (a[j][i])
{
x=j;
break;
}
if (x!=i)
for (int j=1;j<=n;j++)
{
swap(a[i][j],a[x][j]);
swap(ret.a[i][j],ret.a[x][j]);
}
t=inverse(a[i][i]);
for (int j=1;j<=n;j++)
{
a[i][j]=a[i][j]*t%p;
ret.a[i][j]=ret.a[i][j]*t%p;
}
for (int j=1;j<=n;j++)
if (j!=i)
{
t=a[j][i];
for (int k=1;k<=n;k++)
{
a[j][k]=dec(a[j][k],a[i][k]*t%p);
ret.a[j][k]=dec(ret.a[j][k],ret.a[i][k]*t%p);
}
}
}
ret.get();
return ret;
}
}a,b,c;
int main()
{
scanf("%d%d",&n,&p);
a.rd();
b.rd();
m=sqrt(p);
c.init();
for (int i=0;i<m;i++)
{
if (!mp.count(c.h)) mp[c.h]=i;
c=c*a;
if (b.h==c.h)
{
printf("%d\n",i+1);
return 0;
}
}
c=c.inv();
for (int i=1;;i++)
{
b=b*c;
if (mp.count(b.h))
{
printf("%d\n",i*m+mp[b.h]);
return 0;
}
}
}
- O ( k 2 log n ) O(k^2\log n) O(k2logn)递推
bzoj4161 Shlw loves matrixI【2017.5.18】
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxk=4010,p=1000000007;
int n,k,f[maxk],h[maxk];
int inc(int x,int y)
{
x+=y;return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;return x<0?x+p:x;
}
struct mat
{
int a[maxk];
mat operator * (const mat &m) const
{
mat ret;
for (int i=0;i<=2*k-2;i++) ret.a[i]=0;
for (int i=0;i<k;i++)
for (int j=0;j<k;j++)
ret.a[i+j]=inc(ret.a[i+j],(LL)a[i]*m.a[j]%p);
for (int i=2*k-2;i>=k;i--)
for (int j=1;j<=k;j++)
ret.a[i-j]=inc(ret.a[i-j],(LL)ret.a[i]*f[j]%p);
return ret;
}
}a,b;
int main()
{
int ans=0;
scanf("%d%d",&n,&k);
for (int i=1;i<=k;i++)
{
scanf("%d",&f[i]);
f[i]=dec(f[i],0);
}
for (int i=0;i<k;i++)
{
scanf("%d",&h[i]);
h[i]=dec(h[i],0);
}
a.a[1]=1;
b.a[0]=1;
for (int i=n-k+1;i;i>>=1,a=a*a)
if (i&1) b=b*a;
for (int i=k;i<=2*k-2;i++)
for (int j=1;j<=k;j++)
h[i]=inc(h[i],(LL)h[i-j]*f[j]%p);
for (int i=0;i<k;i++)
ans=inc(ans,(LL)b.a[i]*h[k+i-1]%p);
printf("%d\n",ans);
}
【2017.7.15】
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int p=1000000007,maxk=4010;
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int f[maxk],h[maxk],k,n;
struct mat
{
int a[maxk];
mat operator * (const mat &m) const
{
mat ret;
for (int i=0;i<=2*k-2;i++)
ret.a[i]=0;
for (int i=0;i<k;i++)
for (int j=0;j<k;j++)
ret.a[i+j]=inc(ret.a[i+j],(LL)a[i]*m.a[j]%p);
for (int i=2*k-2;i>=k;i--)
{
for (int j=1;j<=k;j++) ret.a[i-j]=inc(ret.a[i-j],(LL)ret.a[i]*f[j]%p);
ret.a[i]=0;
}
return ret;
}
}base,res;
int main()
{
//freopen("d.in","r",stdin);
int ans=0;
scanf("%d%d",&n,&k);
for (int i=1;i<=k;i++)
{
scanf("%d",&f[i]);
if (f[i]<0) f[i]+=p;
}
for (int i=0;i<k;i++)
{
scanf("%d",&h[i]);
if (h[i]<0) h[i]+=p;
}
base.a[1]=1;
res.a[0]=1;
for (n-=k-1;n;n>>=1,base=base*base)
if (n&1) res=res*base;
for (int i=k;i<=2*k-2;i++)
for (int j=1;j<=k;j++)
h[i]=inc(h[i],(LL)f[j]*h[i-j]%p);
for (int i=0;i<k;i++) ans=inc(ans,(LL)res.a[i]*h[k+i-1]%p);
printf("%d\n",ans);
}
- 矩阵树定理
【HEOI2015】bzoi4031 小Z的房间【2017.5.18】
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=110,maxl=15,p=1000000000;
char map[maxl][maxl];
int id[maxl][maxl],a[maxn][maxn],r,c,n;
int main()
{
int flag=0,x,y,t,ans=1;
scanf("%d%d",&r,&c);
for (int i=1;i<=r;i++)
{
scanf("%s",map[i]+1);
for (int j=1;j<=c;j++)
if (map[i][j]=='.')
id[i][j]=++n;
}
for (int i=1;i<=r;i++)
for (int j=1;j<=c;j++)
if (map[i][j]=='.')
{
x=id[i][j];
if (i<r&&map[i+1][j]=='.')
{
y=id[i+1][j];
a[x][y]--;
a[y][x]--;
a[x][x]++;
a[y][y]++;
}
if (j<c&&map[i][j+1]=='.')
{
y=id[i][j+1];
a[x][y]--;
a[y][x]--;
a[x][x]++;
a[y][y]++;
}
}
for (int i=1;i<n;i++)
for (int j=1;j<n;j++)
if (a[i][j]<0) a[i][j]+=p;
for (int i=1;i<n;i++)
{
x=0;
for (int j=i;j<n;j++)
if (a[j][i])
{
x=j;
break;
}
if (!x) continue;
if (x!=i)
{
flag^=1;
for (int j=1;j<n;j++) swap(a[i][j],a[x][j]);
}
for (int j=i+1;j<n;j++)
while (a[j][i])
{
if (a[j][i]<a[i][i])
{
flag^=1;
for (int k=1;k<n;k++) swap(a[j][k],a[i][k]);
}
t=a[j][i]/a[i][i];
for (int k=1;k<n;k++)
a[j][k]=(a[j][k]-(LL)a[i][k]*t%p+p)%p;
}
}
for (int i=1;i<n;i++) ans=(LL)ans*a[i][i]%p;
if (flag) ans=(p-ans)%p;
printf("%d\n",ans);
}
- FFT
bzoj2179 FFT快速傅立叶(FFT)【2017.4.19】
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double pi=acos(-1);
struct Complex
{
double x,y;
Complex operator + (const Complex &c) const
{
return (Complex){x+c.x,y+c.y};
}
Complex operator - (const Complex &c) const
{
return (Complex){x-c.x,y-c.y};
}
Complex operator * (const Complex &c) const
{
return (Complex){x*c.x-y*c.y,x*c.y+y*c.x};
}
}a[200010],b[200010],w[200010],t1,t2;
char s[200010];
int rev[200010],ans[200010],l,m;
void fft(Complex *a,int fl)
{
int x;
for (int i=0;i<l;i++)
if (rev[i]>i) swap(a[i],a[rev[i]]);
for (int i=1;i<=m;i++)
for (int j=0;j<l;j+=1<<i)
{
x=0;
for (int k=j;k<(j+(1<<i-1));k++)
{
t1=a[k];
t2=a[k+(1<<i-1)];
a[k]=t1+t2*w[x];
a[k+(1<<i-1)]=t1-t2*w[x];
x+=fl*(1<<m-i);
if (x<0) x+=l;
}
}
}
int main()
{
int n,nn;
scanf("%d",&n);
scanf("%s",s);
for (int i=0;i<n;i++) a[i].x=s[n-i-1]-'0';
scanf("%s",s);
for (int i=0;i<n;i++) b[i].x=s[n-i-1]-'0';
while ((1<<m)<n*2) m++;
l=1<<m;
w[0]=(Complex){1,0};
w[1]=(Complex){cos(2*pi/l),sin(2*pi/l)};
for (int i=2;i<l;i++)
{
w[i]=w[i/2]*w[i/2];
if (i&1) w[i]=w[i]*w[1];
}
for (int i=0;i<l;i++)
for (int j=0;j<m;j++)
rev[i]|=((i>>j)&1)<<m-j-1;
fft(a,1);
fft(b,1);
for (int i=0;i<l;i++) a[i]=a[i]*b[i];
fft(a,-1);
for (int i=0;i<l;i++) ans[i]=int(a[i].x/l+0.5);
for (int i=0;i<2*n-2;i++)
{
ans[i+1]+=ans[i]/10;
ans[i]%=10;
}
nn=2*n-1;
while (!ans[nn-1]) nn--;
for (int i=nn-1;i>=0;i--) printf("%d",ans[i]);
}
【ZJOI2014】bzoj3527 力【2017.5.18】
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=800010;
const double pi=acos(-1);
struct Complex
{
double a,b;
Complex operator + (const Complex &c) const
{
return (Complex){a+c.a,b+c.b};
}
Complex operator - (const Complex &c) const
{
return (Complex){a-c.a,b-c.b};
}
Complex operator * (const Complex &c) const
{
return (Complex){a*c.a-b*c.b,a*c.b+b*c.a};
}
}w[maxn],a[maxn],b[maxn],t1,t2;
int rev[maxn],n,l,t;
void fft(Complex *a,int flag)
{
int x;
for (int i=0;i<l;i++)
if (rev[i]>i) swap(a[i],a[rev[i]]);
for (int i=1;i<=t;i++)
for (int j=0;j<l;j+=1<<i)
{
x=0;
for (int k=j;k<j+(1<<i-1);k++)
{
t1=a[k];
t2=a[k+(1<<i-1)];
a[k]=t1+t2*w[x];
a[k+(1<<i-1)]=t1-t2*w[x];
x+=flag*(1<<t-i);
if (x<0) x+=l;
}
}
}
int main()
{
scanf("%d",&n);
for (int i=0;i<n;i++) scanf("%lf",&a[i].a);
for (int i=0;i<n-1;i++) b[i].a=-1/((double)(n-i-1)*(n-i-1));
for (int i=n;i<2*n-1;i++) b[i].a=1/((double)(i-n+1)*(i-n+1));
l=1,t=0;
while (l<4*n-3) l<<=1,t++;
for (int i=0;i<l;i++) w[i]=(Complex){cos(2*pi*i/l),sin(2*pi*i/l)};
for (int i=0;i<l;i++)
for (int j=0;j<t;j++) rev[i]|=((i>>j)&1)<<(t-j-1);
fft(a,1);
fft(b,1);
for (int i=0;i<l;i++) a[i]=a[i]*b[i];
fft(a,-1);
for (int i=n-1;i<2*n-1;i++) printf("%.3f\n",a[i].a/l);
}
- 辛普森自适应积分
计算几何
- 射线法
- 凸包
- 旋转卡壳
- 半平面交
图论
- 树链剖分
- LCT
【HNOI2010】bzoj2002 弹飞绵羊
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=400010;
int rd()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
int fa[maxn],son[maxn][2],siz[maxn],a[maxn],inv[maxn],sta[maxn],n;
void down(int x)
{
if (inv[x])
{
inv[x]=0;
swap(son[x][0],son[x][1]);
if (son[x][0]) inv[son[x][0]]^=1;
if (son[x][1]) inv[son[x][1]]^=1;
}
}
void up(int x)
{
down(x);
siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
}
int isroot(int x)
{
return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
void rot(int u,int f)
{
int v=son[u][f],x=son[v][f^1],y=fa[u];
if (son[y][0]==u) son[y][0]=v;
if (son[y][1]==u) son[y][1]=v;
fa[v]=y;
son[v][f^1]=u;
fa[u]=v;
son[u][f]=x;
if (x) fa[x]=u;
up(u);
up(v);
}
void splay(int u)
{
int top=0,x,y,fx,fy;
for (int i=u;;i=fa[i])
{
sta[++top]=i;
if (isroot(i)) break;
}
for (;top;top--) down(sta[top]);
while (!isroot(u))
{
x=fa[u];
fx=son[x][1]==u;
if (isroot(x)) rot(x,fx);
else
{
y=fa[x];
fy=son[y][1]==x;
if (fx==fy) rot(y,fy),rot(x,fx);
else rot(x,fx),rot(y,fy);
}
}
}
void access(int u)
{
int v=0;
while (u)
{
splay(u);
son[u][1]=v;
up(u);
v=u;
u=fa[u];
}
}
void makeroot(int x)
{
access(x);
splay(x);
inv[x]^=1;
up(x);
}
void link(int x,int y)
{
makeroot(y);
fa[x]=y;
}
void cut(int x,int y)
{
makeroot(y);
access(x);
splay(x);
son[x][0]=fa[y]=0;
up(x);
}
int qry(int x)
{
makeroot(n+1);
access(x);
splay(x);
return siz[x]-1;
}
int main()
{
int q,opt,x,y;
n=rd();
for (int i=1;i<=n;i++) siz[i]=1;
for (int i=1;i<=n;i++)
{
a[i]=rd();
if (i+a[i]>n) a[i]=n-i+1;
link(i,i+a[i]);
}
q=rd();
while (q--)
{
opt=rd();
if (opt==1) printf("%d\n",qry(rd()+1));
else
{
x=rd()+1;
y=rd();
cut(x,x+a[x]);
a[x]=y;
if (x+a[x]>n) a[x]=n-x+1;
link(x,x+a[x]);
}
}
}
bzoj2631 tree【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
#define UI unsigned int
const int maxn=200010,p=51061;
int rd()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
char rdc()
{
char c=getchar();
while (c!='+'&&c!='*'&&c!='/'&&c!='-') c=getchar();
return c;
}
int inc(int x,int y)
{
x+=y;return x>=p?x-p:x;
}
int son[maxn][2],fa[maxn],tagp[maxn],tagm[maxn],sum[maxn],val[maxn],siz[maxn],inv[maxn],
sta[maxn],
n;
int is(int u)
{
return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;
}
void down(int u)
{
int v;
if (inv[u])
{
inv[u]=0;
swap(son[u][0],son[u][1]);
if (v=son[u][0]) inv[v]^=1;
if (v=son[u][1]) inv[v]^=1;
}
if (tagm[u]!=1)
{
val[u]=(UI)val[u]*tagm[u]%p;
sum[u]=(UI)sum[u]*tagm[u]%p;
if (v=son[u][0])
{
tagm[v]=(UI)tagm[v]*tagm[u]%p;
tagp[v]=(UI)tagp[v]*tagm[u]%p;
}
if (v=son[u][1])
{
tagm[v]=(UI)tagm[v]*tagm[u]%p;
tagp[v]=(UI)tagp[v]*tagm[u]%p;
}
tagm[u]=1;
}
if (tagp[u])
{
val[u]=inc(val[u],tagp[u]);
sum[u]=inc(sum[u],(UI)tagp[u]*siz[u]%p);
if (v=son[u][0]) tagp[v]=inc(tagp[v],tagp[u]);
if (v=son[u][1]) tagp[v]=inc(tagp[v],tagp[u]);
tagp[u]=0;
}
}
void up(int u)
{
down(u);
if (son[u][0]) down(son[u][0]);
if (son[u][1]) down(son[u][1]);
int v;
sum[u]=val[u];
siz[u]=1;
if (v=son[u][0])
{
sum[u]=inc(sum[u],sum[v]);
siz[u]=siz[u]+siz[v];
}
if (v=son[u][1])
{
sum[u]=inc(sum[u],sum[v]);
siz[u]=siz[u]+siz[v];
}
}
void rot(int u,int f)
{
int v=son[u][f],x=son[v][f^1],y=fa[u];
if (!is(u)) son[y][son[y][1]==u]=v;
fa[v]=y;
son[v][f^1]=u;
fa[u]=v;
son[u][f]=x;
if (x) fa[x]=u;
up(u);
up(v);
}
void splay(int u)
{
int v,x,y,xx,yy,t=u,top=0;
while (1)
{
sta[++top]=t;
if (is(t)) break;
t=fa[t];
}
for (;top;top--) down(sta[top]);
while (!is(u))
{
x=fa[u];
xx=son[x][1]==u;
if (is(x)) rot(x,xx);
else
{
y=fa[x];
yy=son[y][1]==x;
if (xx==yy) rot(y,yy),rot(x,xx);
else rot(x,xx),rot(y,yy);
}
}
}
void access(int u)
{
int v=0,t=u;
while (u)
{
splay(u);
son[u][1]=v;
up(u);
v=u;
u=fa[u];
}
splay(t);
}
void make(int u)
{
access(u);
inv[u]^=1;
up(u);
}
void link(int u,int v)
{
make(u);
fa[u]=v;
}
void cut(int u,int v)
{
make(u);
access(v);
son[v][0]=fa[u]=0;
up(v);
}
int query(int u,int v)
{
make(u);
access(v);
return sum[v];
}
void modip(int u,int v,int x)
{
make(u);
access(v);
tagp[v]=inc(tagp[v],x);
}
void modim(int u,int v,int x)
{
make(u);
access(v);
tagp[v]=(UI)tagp[v]*x%p;
tagm[v]=(UI)tagm[v]*x%p;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
char c;
int u,v,x,y,q;
n=rd();
q=rd();
for (int i=1;i<=n;i++) sum[i]=val[i]=tagm[i]=siz[i]=1;
for (int i=1;i<n;i++)
{
u=rd();
v=rd();
link(u,v);
}
while (q--)
{
c=rdc();
u=rd();
v=rd();
if (c=='/') printf("%d\n",query(u,v));
else
{
x=rd();
if (c=='+') modip(u,v,x);
else if (c=='*') modim(u,v,x);
else
{
y=rd();
cut(u,v);
link(x,y);
}
}
}
}
- 点分治
poj1741 Tree【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=10010;
struct node
{
int bel,dis;
bool operator < (const node &n) const
{
return dis<n.dis;
}
}a[maxn];
int fir[maxn],vis[maxn],ne[2*maxn],to[2*maxn],w[2*maxn],size[maxn],val[maxn],sum[maxn],
rt,n,m,ans,S,tot;
void add(int num,int u,int v,int x)
{
ne[num]=fir[u];
fir[u]=num;
to[num]=v;
w[num]=x;
}
void dfs1(int u,int fa)
{
size[u]=1;
val[u]=0;
for (int i=fir[u];i;i=ne[i])
if (to[i]!=fa&&!vis[to[i]])
{
dfs1(to[i],u);
size[u]+=size[to[i]];
val[u]=max(val[u],size[to[i]]);
}
val[u]=max(val[u],S-size[u]);
if (rt==-1||val[u]<val[rt]) rt=u;
}
void dfs2(int u,int fa,int b,int d)
{
size[u]=1;
a[++tot]=(node){b,d};
for (int i=fir[u];i;i=ne[i])
if (to[i]!=fa&&!vis[to[i]])
{
dfs2(to[i],u,b,d+w[i]);
size[u]+=size[to[i]];
}
}
void solve(int u)
{
int r,num=0,s=0;
rt=-1;
dfs1(u,-1);
r=rt;
a[tot=1]=(node){0,0};
for (int i=fir[r];i;i=ne[i])
if (!vis[to[i]])
dfs2(to[i],r,++num,w[i]);
sort(a+1,a+tot+1);
for (int i=0;i<=num;i++) sum[i]=0;
for (int i=tot,j=0;i;i--)
{
while (j<tot&&a[j+1].dis+a[i].dis<=m) sum[a[++j].bel]++;
ans+=j-sum[a[i].bel];
}
vis[r]=1;
for (int i=fir[r];i;i=ne[i])
if (!vis[to[i]])
{
S=size[to[i]];
solve(to[i]);
}
}
void solve()
{
int u,v,x;
for (int i=1;i<=n;i++) fir[i]=vis[i]=0;
ans=0;
for (int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&x);
add(i*2,u,v,x);
add(i*2+1,v,u,x);
}
S=n;
solve(1);
printf("%d\n",ans/2);
}
int main()
{
while (scanf("%d%d",&n,&m)&&n) solve();
}
- 边分治
- 动态点分治
【ZJOI2007】bzoj1095 捉迷藏【2017.5.18】
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100010;
struct heap
{
priority_queue<int> a,b;
void ins(int x)
{
a.push(x);
}
void del(int x)
{
b.push(x);
}
int size()
{
return a.size()-b.size();
}
int top()
{
while (!b.empty()&&a.top()==b.top())
{
a.pop();
b.pop();
}
return a.top();
}
int get()
{
int x=top();
del(x);
int y=top();
ins(x);
return x+y;
}
}q1[maxn],q2[maxn],q3;
int fir[maxn],ne[2*maxn],to[2*maxn],
vis[maxn],size[maxn],val[maxn],fa[maxn],flag[maxn],
mn[2*maxn][20],pos[maxn],dep[maxn],log[2*maxn],
n,rt,clo;
void add(int num,int u,int v)
{
ne[num]=fir[u];
fir[u]=num;
to[num]=v;
}
void dfs0(int u,int fa,int d)
{
dep[u]=d;
mn[pos[u]=++clo][0]=d;
for (int i=fir[u];i;i=ne[i])
if (to[i]!=fa)
{
dfs0(to[i],u,d+1);
mn[++clo][0]=d;
}
}
void dfs1(int u,int fa)
{
size[u]=1;
for (int i=fir[u];i;i=ne[i])
if (!vis[to[i]]&&to[i]!=fa)
{
dfs1(to[i],u);
size[u]+=size[to[i]];
}
}
int dfs2(int u,int fa,int S)
{
int ret=-1,x;
val[u]=S-size[u];
for (int i=fir[u];i;i=ne[i])
if (!vis[to[i]]&&to[i]!=fa)
{
x=dfs2(to[i],u,S);
val[u]=max(val[u],size[to[i]]);
if (ret==-1||val[x]<val[ret]) ret=x;
}
if (ret==-1||val[u]<val[ret]) ret=u;
return ret;
}
void dfs3(int u,int fa,int bel,int dis)
{
q1[bel].ins(dis);
for (int i=fir[u];i;i=ne[i])
if (!vis[to[i]]&&to[i]!=fa)
dfs3(to[i],u,bel,dis+1);
}
int solve(int u)
{
dfs1(u,-1);
int r=dfs2(u,-1,size[u]),x;
vis[r]=1;
for (int i=fir[r];i;i=ne[i])
if (!vis[to[i]])
{
x=solve(to[i]);
dfs3(to[i],r,x,1);
fa[x]=r;
q2[r].ins(q1[x].top());
}
q2[r].ins(0);
vis[r]=0;
if (q2[r].size()>=2) q3.ins(q2[r].get());
return r;
}
int dis(int u,int v)
{
int x=pos[u],y=pos[v],k;
if (x>y) swap(x,y);
k=log[y-x+1];
return dep[u]+dep[v]-2*min(mn[x][k],mn[y-(1<<k)+1][k]);
}
void ins(int u)
{
if (q2[u].size()>=2) q3.del(q2[u].get());
q2[u].ins(0);
if (q2[u].size()>=2) q3.ins(q2[u].get());
for (int i=u;fa[i];i=fa[i])
{
if (q2[fa[i]].size()>=2) q3.del(q2[fa[i]].get());
if (q1[i].size()) q2[fa[i]].del(q1[i].top());
q1[i].ins(dis(u,fa[i]));
if (q1[i].size()) q2[fa[i]].ins(q1[i].top());
if (q2[fa[i]].size()>=2) q3.ins(q2[fa[i]].get());
}
}
void del(int u)
{
if (q2[u].size()>=2) q3.del(q2[u].get());
q2[u].del(0);
if (q2[u].size()>=2) q3.ins(q2[u].get());
for (int i=u;fa[i];i=fa[i])
{
if (q2[fa[i]].size()>=2) q3.del(q2[fa[i]].get());
if (q1[i].size()) q2[fa[i]].del(q1[i].top());
q1[i].del(dis(u,fa[i]));
//printf("%d\n",q1[i].size());
if (q1[i].size()) q2[fa[i]].ins(q1[i].top());
if (q2[fa[i]].size()>=2) q3.ins(q2[fa[i]].get());
}
}
int main()
{
int u,v,q,now;
char c[3];
scanf("%d",&n);
for (int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(i*2,u,v);
add(i*2+1,v,u);
}
dfs0(1,-1,1);
for (int i=1;(1<<i)<=clo;i++) log[1<<i]=i;
for (int i=3;i<=clo;i++)
if (!log[i]) log[i]=log[i-1];
for (int k=1;k<=log[clo];k++)
for (int i=1;i+(1<<k)-1<=clo;i++)
mn[i][k]=min(mn[i][k-1],mn[i+(1<<k-1)][k-1]);
rt=solve(1);
now=n;
scanf("%d",&q);
while (q--)
{
scanf("%s",c);
if (c[0]=='C')
{
scanf("%d",&u);
if (flag[u]) ins(u),now++;
else del(u),now--;
flag[u]^=1;
}
else
{
if (now==0) printf("-1\n");
else if (now==1) printf("0\n");
else printf("%d\n",q3.top());
}
}
}
- 2-SAT
poj3678 Katu Puzzle【2017.5.19】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=2010,maxm=2000010;
int fir[maxn],ne[maxm],to[maxm],dfn[maxn],low[maxn],sta[maxn],bel[maxn],in[maxn],
n,m,num,clo,tot,top;
void add(int u,int v)
{
num++;
ne[num]=fir[u];
fir[u]=num;
to[num]=v;
}
void dfs(int u)
{
int x;
dfn[u]=low[u]=++clo;
sta[++top]=u;
in[u]=1;
for (int i=fir[u];i;i=ne[i])
if (!dfn[to[i]])
{
dfs(to[i]);
low[u]=min(low[u],low[to[i]]);
}
else if (in[to[i]]) low[u]=min(low[u],dfn[to[i]]);
if (low[u]==dfn[u])
{
tot++;
do
{
x=sta[top--];
bel[x]=tot;
in[x]=0;
}
while (x!=u);
}
}
int main()
{
int u,v,x;
char s[10];
scanf("%d%d",&n,&m);
while (m--)
{
scanf("%d%d%d%s",&u,&v,&x,s);
switch (s[0])
{
case 'A':
if (x==0)
{
add(v*2+1,u*2);
add(u*2+1,v*2);
}
else
{
add(u*2,u*2+1);
add(v*2,v*2+1);
}
break;
case 'O':
if (x==0)
{
add(u*2+1,u*2);
add(v*2+1,v*2);
}
else
{
add(u*2,v*2+1);
add(v*2,u*2+1);
}
break;
case 'X':
if (x==0)
{
add(u*2,v*2);
add(v*2,u*2);
add(u*2+1,v*2+1);
add(v*2+1,u*2+1);
}
else
{
add(u*2,v*2+1);
add(v*2,u*2+1);
add(u*2+1,v*2);
add(v*2+1,u*2);
}
break;
}
}
for (int i=0;i<n*2;i++)
if (!dfn[i]) dfs(i);
for (int i=0;i<n;i++)
if (bel[i*2]==bel[i*2+1])
{
printf("NO\n");
return 0;
}
printf("YES\n");
}
动态规划
- 斜率优化dp
【APIO2010】bzoj1911 特别行动队
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=1000010;
int rd()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
LL dp[maxn],s[maxn],h[maxn],g[maxn],a,b,c;
int que[maxn],n;
double get(int i,int j)
{
return (double)(h[j]-h[i])/(s[j]-s[i]);
}
int main()
{
int hd=1,tl=1;
n=rd();
a=rd();
b=rd();
c=rd();
for (int i=1;i<=n;i++) s[i]=s[i-1]+rd();
for (int i=1;i<=n;i++)
{
while (hd<tl&&get(que[hd],que[hd+1])<=-2*a*s[i]) hd++;
dp[i]=dp[que[hd]]+a*(s[i]-s[que[hd]])*(s[i]-s[que[hd]])+b*(s[i]-s[que[hd]])+c;
h[i]=-a*s[i]*s[i]+b*s[i]-dp[i];
while (hd<tl&&get(que[tl-1],que[tl])>=get(que[tl],i)) tl--;
que[++tl]=i;
}
printf("%lld\n",dp[n]);
}
- 插头dp
【SCOI2011】bzoj2331 地板【2017.5.19】
#include<cstdio>
#include<algorithm>
using namespace std;
const int p=20110520;
char mp[110][110];
int dp[2][4200010],last[4200010],f[2][4200010],
r,c,clo,tot,y;
int inc(int x,int y)
{
x+=y;return x>=p?x-p:x;
}
void upd(int x)
{
if (last[x]==clo+1) dp[clo&1^1][x]=inc(dp[clo&1^1][x],y);
else
{
last[x]=clo+1;
f[clo&1^1][++tot]=x;
dp[clo&1^1][x]=y;
}
}
int main()
{
int x,t1,ans=0;
scanf("%d%d",&r,&c);
for (int i=1;i<=r;i++) scanf("%s",mp[i]+1);
if (r<c)
{
for (int i=1;i<=c;i++)
for (int j=i+1;j<=c;j++)
swap(mp[i][j],mp[j][i]);
swap(r,c);
}
f[1][tot=1]=0;
dp[1][0]=1;
for (int i=1;i<=r;i++)
for (int j=1;j<=c;j++)
{
clo++;
t1=tot;
tot=0;
for (int k=1;k<=t1;k++)
{
x=f[clo&1][k];
y=dp[clo&1][x];
if (mp[i][j]=='*')
{
if (!(x&1)&&!((x>>2)&1)) upd(x>>2);
continue;
}
if (!(x&1))
{
if (!(x&4))
{
upd((x>>2)|(1<<2*c));
if (j<c)
{
upd((x>>2)|1);
upd((x>>2)|3|(3<<2*c));
}
}
else if (!(x&8))
{
upd(((x>>2)^1)|(1<<2*c));
if (j<c) upd((x>>2)|3);
}
else
{
upd((x>>2)^3);
upd(((x>>2)^3)|(3<<2*c));
}
}
else if (!(x&2))
{
if (!(x&4))
{
if (j<c) upd((x>>2)|1);
upd((x>>2)|(3<<2*c));
}
else if (!(x&8)) upd((x>>2)^1);
}
else
{
if (!(x&4))
{
upd(x>>2);
if (j<c) upd((x>>2)|3);
}
}
}
}
printf("%d\n",last[0]==clo+1?dp[clo&1^1][0]:0);
}
- 数位dp
- 四边形不等式
其他算法
- CDQ分治
bzoj3262 陌上花开【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010,maxm=200010;
int rd()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
struct flower
{
int a,b,c,res,num;
bool operator < (const flower &f) const
{
if (a!=f.a) return a<f.a;
if (b!=f.b) return b<f.b;
return c<f.c;
}
}a[maxn],b[maxn];
int s[maxm],ans[maxn],n,m;
void add(int k,int x)
{
for (;k<=m;k+=k&-k) s[k]+=x;
}
int qry(int k)
{
int ret=0;
for (;k;k-=k&-k) ret+=s[k];
return ret;
}
void solve(int l,int r)
{
if (l==r) return;
int mid=(l+r)/2;
solve(l,mid);
solve(mid+1,r);
for (int i=l;i<=r;i++) b[i]=a[i];
for (int i=l,j=mid+1,now=l;i<=mid||j<=r;)
if (j>r||(i<=mid&&b[i].b<=b[j].b))
{
add(b[i].c,b[i].num);
a[now++]=b[i++];
}
else
{
b[j].res+=qry(b[j].c);
a[now++]=b[j++];
}
for (int i=l;i<=mid;i++) add(b[i].c,-b[i].num);
}
int main()
{
int N=1;
n=rd();
m=rd();
for (int i=1;i<=n;i++)
{
a[i].a=rd();
a[i].b=rd();
a[i].c=rd();
a[i].num=1;
}
sort(a+1,a+n+1);
b[1]=a[1];
for (int i=2;i<=n;i++)
if (a[i-1]<a[i]) b[++N]=a[i];
else b[N].num++;
for (int i=1;i<=N;i++) a[i]=b[i];
solve(1,N);
for (int i=1;i<=N;i++) ans[a[i].res+a[i].num-1]+=a[i].num;
for (int i=0;i<n;i++) printf("%d\n",ans[i]);
}
- 整体二分
bzoj2738 矩阵乘法【2017.5.16】
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=510,maxq=60010;
int rd()
{
int x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
struct qry
{
int x1,y1,x2,y2,id,res,k;
}f[maxq],g[maxq];
struct node
{
int x,y,v;
bool operator < (const node &n) const
{
return v<n.v;
}
}a[maxn*maxn];
int s[maxn][maxn],ans[maxq],n,q,tot;
void add(node a)
{
for (int i=a.x;i<=n;i+=i&-i)
for (int j=a.y;j<=n;j+=j&-j)
s[i][j]++;
}
void dec(node a)
{
for (int i=a.x;i<=n;i+=i&-i)
for (int j=a.y;j<=n;j+=j&-j)
s[i][j]--;
}
int query(qry a)
{
int ret=0;
for (int i=a.x2;i;i-=i&-i)
for (int j=a.y2;j;j-=j&-j)
ret+=s[i][j];
for (int i=a.x1-1;i;i-=i&-i)
for (int j=a.y2;j;j-=j&-j)
ret-=s[i][j];
for (int i=a.x2;i;i-=i&-i)
for (int j=a.y1-1;j;j-=j&-j)
ret-=s[i][j];
for (int i=a.x1-1;i;i-=i&-i)
for (int j=a.y1-1;j;j-=j&-j)
ret+=s[i][j];
return ret;
}
void solve(int l,int r,int L,int R)
{
if (L==R)
{
for (int i=l;i<=r;i++) f[i].res=a[L].v;
return;
}
int mid=(L+R)/2,m=r,x;
for (int i=L;i<=mid;i++) add(a[i]);
for (int i=l,j=l,k=r;i<=r;i++)
{
x=query(f[i]);
if (f[i].k<=x) g[j++]=f[i];
else
{
f[i].k-=x;
g[k--]=f[i];
m=k;
}
}
for (int i=L;i<=mid;i++) dec(a[i]);
for (int i=l;i<=r;i++) f[i]=g[i];
solve(l,m,L,mid);
solve(m+1,r,mid+1,R);
}
int main()
{
int x1,y1,x2,y2,k;
n=rd();
q=rd();
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
a[++tot]=(node){i,j,rd()};
for (int i=1;i<=q;i++)
{
x1=rd();
y1=rd();
x2=rd();
y2=rd();
k=rd();
f[i]=(qry){x1,y1,x2,y2,i,0,k};
}
sort(a+1,a+tot+1);
solve(1,q,1,tot);
for (int i=1;i<=q;i++) ans[f[i].id]=f[i].res;
for (int i=1;i<=q;i++) printf("%d\n",ans[i]);
}
【ZJOI2013】bzoj3110 K大数查询【2017.7.14】
#include<cstdio>
#include<algorithm>
using namespace std;
#define UI unsigned int
const int maxn=50010,maxt=2000000;
int rdi()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9')
{
if (c=='-') f=-1;
c=getchar();
}
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
UI rdu()
{
UI x=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
struct str
{
int l,r,id,f;
UI x;
}a[maxn],b[maxn],c[maxn];
UI sum[maxt];
int n,m,o,val[maxn],ord[maxn],ans[maxn],tag[maxt];
void down(int u,int L,int R)
{
if (L<R)
{
tag[u*2]+=tag[u];
tag[u*2+1]+=tag[u];
}
sum[u]+=(UI)tag[u]*(R-L+1);
tag[u]=0;
}
UI qry(int u,int L,int R,int l,int r)
{
down(u,L,R);
if (l<=L&&R<=r) return sum[u];
int mid=(L+R)/2;
UI ret=0;
if (l<=mid) ret=qry(u*2,L,mid,l,r);
if (r>mid) ret+=qry(u*2+1,mid+1,R,l,r);
return ret;
}
void modi(int u,int L,int R,int l,int r,int x)
{
if (l<=L&&R<=r)
{
tag[u]+=x;
return;
}
down(u,L,R);
int mid=(L+R)/2;
if (l<=mid) modi(u*2,L,mid,l,r,x);
if (r>mid) modi(u*2+1,mid+1,R,l,r,x);
down(u*2,L,mid);
down(u*2+1,mid+1,R);
sum[u]=sum[u*2]+sum[u*2+1];
}
void solve(int L,int R,int l,int r)
{
if (l==r)
{
for (int i=L;i<=R;i++)
if (a[i].f==2) ans[a[i].id]=l;
return;
}
int mid=(l+r)/2,n1=0,n2=0;
UI x;
for (int i=L;i<=R;i++)
if (a[i].f==1)
{
if ((int)a[i].x>mid)
{
modi(1,1,n,a[i].l,a[i].r,1);
c[++n2]=a[i];
}
else b[++n1]=a[i];
}
else
{
x=qry(1,1,n,a[i].l,a[i].r);
if (x>=a[i].x) c[++n2]=a[i];
else
{
a[i].x-=x;
b[++n1]=a[i];
}
}
for (int i=L;i<=R;i++)
if (a[i].f==1&&(int)a[i].x>mid)
modi(1,1,n,a[i].l,a[i].r,-1);
for (int i=1;i<=n1;i++) a[L+i-1]=b[i];
for (int i=1;i<=n2;i++) a[L+n1+i-1]=c[i];
solve(L,L+n1-1,l,mid);
solve(L+n1,R,mid+1,r);
}
int main()
{
//freopen("b.in","r",stdin);
//freopen("b.out","w",stdout);
n=rdi();
m=rdi();
for (int i=1;i<=m;i++)
{
a[i].f=rdi();
a[i].l=rdi();
a[i].r=rdi();
if (a[i].f==1) val[i]=ord[++o]=rdi();
else a[i].x=rdu();
a[i].id=i;
}
sort(ord+1,ord+o+1);
o=unique(ord+1,ord+o+1)-ord-1;
for (int i=1;i<=m;i++)
if (a[i].f==1) a[i].x=lower_bound(ord+1,ord+o+1,val[i])-ord;
solve(1,m,1,o);
for (int i=1;i<=m;i++)
if (ans[i]) printf("%d\n",ord[ans[i]]);
}