Loading

板子

ST表

递推:f[i][j]=max(f[i][j-1],f[i+(1<<j)][j-1]
查询:max(f[l][x],f[r-(1<<x)+1][x])x=log2(r-l+1)

费用流

#include<bits/stdc++.h>
#define inf 2147483647
#define R register
using namespace std;
struct node
{
    int to,val,next,flow;
}a[100005];
int n,m,S,T,x,y,z,v,q,ans,ans1,tot,head[5005],dis[5005];
bool bj[5005];
inline void add(int x,int y,int z,int v)
{
    a[tot].to=y;
    a[tot].flow=z;
    a[tot].val=v;
    a[tot].next=head[x];
    head[x]=tot;
    tot++;
}
inline bool OK()
{
    int plus=inf;
    for (R int i=1;i<=n;i++)
        if (bj[i])
            for (R int j=head[i];j!=-1;j=a[j].next)
                if (!bj[a[j].to]&&a[j].flow) plus=min(plus,dis[a[j].to]+a[j].val-dis[i]);
    if (plus==inf) return false;
    for (R int i=1;i<=n;i++)
    {
        if (bj[i])
        {
            bj[i]=false;
            dis[i]+=plus;
        }
    }
    return true;
}
inline int mnmx(int now,int sum)
{
    if (now==T)
    {
        ans1+=dis[S]*sum;
        return sum;
    }
    bj[now]=true;
    int x,u;
    for (R int i=head[now];i!=-1;i=a[i].next)
    {
        u=a[i].to;
        if (!bj[u]&&dis[u]+a[i].val==dis[now]&&a[i].flow)
        {
            x=mnmx(u,min(sum,a[i].flow));
            if (x)
            {
                a[i].flow-=x;
                a[i^1].flow+=x;
                return x;
            }
        }
    }
    return 0;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&S,&T);
    for (R int i=1;i<=n;i++)
        head[i]=-1;
    for (R int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&x,&y,&z,&v);
        add(x,y,z,v);
        add(y,x,0,-v);
    }
    bj[S]=true;
    while (OK())
    {
        q=mnmx(S,inf);
        while (q)
        {
            ans+=q;
            memset(bj,false,sizeof(bj));
            q=mnmx(S,inf);
        }
    }
    printf("%d %d\n",ans,ans1);
    return 0;
}

无旋treap

#include<cstdio>
#include<stdlib.h>
using namespace std;
int n,pd,x,size[100005],rd[100005],val[100005],son[100005][3],root,tot;
void pushup(int x)
{
    size[x]=size[son[x][0]]+size[son[x][1]]+1;
}
int makenum(int v)
{
    tot++;
    son[tot][0]=son[tot][1]=0;
    rd[tot]=rand();
    val[tot]=v;
    size[tot]=1;
    return tot;
}
void split(int now,int v,int &x,int &y)
{
    if (!now)
    {
        x=y=0;
        return;
    }
    if (val[now]<=v)
    {
        x=now;
        split(son[now][1],v,son[now][1],y);
        pushup(x);
    }
    else
    {
        y=now;
        split(son[now][0],v,x,son[now][0]);
        pushup(y);
    }
}
int merge(int x,int y)
{
    if (!x||!y) return x+y;
    if (rd[x]>rd[y])
    {
        son[x][1]=merge(son[x][1],y);
        pushup(x);
        return x;
    }
    else
    {
        son[y][0]=merge(x,son[y][0]);
        pushup(y);
        return y;
    }
}
void ins(int v)
{
    int x,y;
    split(root,v,x,y);
    root=merge(merge(x,makenum(v)),y);
}
void del(int v)
{
    int x,y,z;
    split(root,v-1,x,y);
    split(y,v,y,z);
    y=merge(son[y][0],son[y][1]);
    root=merge(merge(x,y),z);
}
int get_rank(int v)
{
    int x,y;
    split(root,v-1,x,y);
    int ans=size[x]+1;
    root=merge(x,y);
    return ans;
}
int get_sum(int now,int v)
{
    if (v<=size[son[now][0]]) return get_sum(son[now][0],v);
    if (v<=size[son[now][0]]+1) return now;
    else return get_sum(son[now][1],v-size[son[now][0]]-1);
}
int get_pre(int v)
{
    int x,y;
    split(root,v-1,x,y);
    int ans=val[get_sum(x,size[x])];
    root=merge(x,y);
    return ans;
}
int get_suc(int v)
{
    int x,y;
    split(root,v,x,y);
    int ans=val[get_sum(y,1)];
    root=merge(x,y);
    return ans;
}
int main()
{
    scanf("%d",&n);
    while (n--)
    {
        scanf("%d%d",&pd,&x);
        if (pd==1) ins(x);
        if (pd==2) del(x);
        if (pd==3) printf("%d\n",get_rank(x));
        if (pd==4) printf("%d\n",val[get_sum(root,x)]);
        if (pd==5) printf("%d\n",get_pre(x));
        if (pd==6) printf("%d\n",get_suc(x));
    }
    return 0;
}

SA(后缀数组)

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1000005
using namespace std;
int all=122,n,num,fir[N],t[N],sec[N],sa[N];
char s[N];
int main()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	for (int i=1;i<=n;++i)
		fir[i]=s[i],t[fir[i]]++;
	for (int i=1;i<=all;++i)
		t[i]+=t[i-1];
	for (int i=n;i;--i)
		sa[t[fir[i]]--]=i;
	for (int k=1;k<=n;k<<=1)
	{
		num=0;
		for (int i=n-k+1;i<=n;++i)
			sec[++num]=i;
		for (int i=1;i<=n;++i)
			if (sa[i]>k) sec[++num]=sa[i]-k;
		for (int i=1;i<=all;++i)
			t[i]=0;
		for (int i=1;i<=n;++i)
			++t[fir[i]];
		for (int i=1;i<=all;++i)
			t[i]+=t[i-1]; 
		for (int i=n;i;--i)
			sa[t[fir[sec[i]]]--]=sec[i],sec[i]=0;
		swap(fir,sec);
		fir[sa[1]]=1;
		num=1;
		for (int i=2;i<=n;++i)
		{
			if (sec[sa[i]]==sec[sa[i-1]]&&sec[sa[i]+k]==sec[sa[i-1]+k]) fir[sa[i]]=num;
			else fir[sa[i]]=++num;
		}
		if (num==n) break;
		all=num;
	}
	for (int i=1;i<=n;++i)
		printf("%d ",sa[i]);
	return 0;
}

三维偏序(cdq分治)

#include<cstdio>
#include<algorithm>
#define N 200005
using namespace std;
struct node
{
	int a,b,c,ans,cnt;
}q[N],p[N];
int n,k,m,num,tr[N<<2],ans[N];
int lowbit(int x) {return x&(-x);}
bool cmp1(node x,node y)
{
	if (x.a<y.a) return true;
	if (x.a>y.a) return false;
	if (x.b==y.b) return x.c<y.c;
	else return x.b<y.b;
}
bool cmp2(node x,node y)
{
	if (x.b<y.b) return true;
	if (x.b>y.b) return false;
	return x.c<y.c;
}
void add(int x,int y)
{
	for (;x<=k;x+=lowbit(x)) tr[x]+=y;
}
int query(int x)
{
	int res=0;
	for (;x;x-=lowbit(x)) res+=tr[x];
	return res;
}
void cdq(int l,int r)
{
	if (l==r) return;
	int mid=(l+r)>>1;
	cdq(l,mid);cdq(mid+1,r);
	sort(p+l,p+mid+1,cmp2);sort(p+mid+1,p+r+1,cmp2);
	int i,j=l;
	for (int i=mid+1;i<=r;++i)
	{
		while (p[i].b>=p[j].b&&j<=mid)
		{
			add(p[j].c,p[j].cnt);
			j++;
		}
		p[i].ans+=query(p[i].c);
	}
	for (int i=l;i<j;++i)
		add(p[i].c,-p[i].cnt);
}
int main()
{
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;++i)
		scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c);
	sort(q+1,q+n+1,cmp1);
	for (int i=1;i<=n;++i)
	{
		++num;
		if (q[i].a!=q[i+1].a||q[i].b!=q[i+1].b||q[i].c!=q[i+1].c)
		{
			p[++m].a=q[i].a;p[m].b=q[i].b;p[m].c=q[i].c;
			p[m].cnt=num;num=0;
		}
	}
	cdq(1,m);
	for (int i=1;i<=n;++i)
		ans[p[i].ans+p[i].cnt-1]+=p[i].cnt;
	for (int i=0;i<n;++i)
		printf("%d\n",ans[i]);
	return 0;
}

主席树

#include<cstdio>
#include<algorithm>
#define N 200005
using namespace std;
struct node
{
	int rt,lson,rson,sum;
}tr[N<<5];
int n,m,q,p,l,r,k,ans,cnt,a[N],b[N];
void build(int &root,int l,int r)
{
	root=++cnt;
	if (l==r) return;
	int mid=(l+r)>>1;
	build(tr[root].lson,l,mid);
	build(tr[root].rson,mid+1,r);
}
int modify(int now,int l,int r)
{
	int nxt=++cnt;
	tr[nxt].lson=tr[now].lson;
	tr[nxt].rson=tr[now].rson;
	tr[nxt].sum=tr[now].sum+1;
	if (l==r) return nxt;
	int mid=(l+r)>>1;
	if (p<=mid) tr[nxt].lson=modify(tr[nxt].lson,l,mid);
	else tr[nxt].rson=modify(tr[nxt].rson,mid+1,r);
	return nxt;
}
int query(int u,int v,int l,int r,int k)
{
	int res=0,mid=(l+r)>>1,x=tr[tr[v].lson].sum-tr[tr[u].lson].sum;
	if (l==r) return l;
	if (x>=k) res=query(tr[u].lson,tr[v].lson,l,mid,k);
	else res=query(tr[u].rson,tr[v].rson,mid+1,r,k-x);
	return res;
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;++i)
		scanf("%d",&a[i]),b[i]=a[i];
	sort(b+1,b+n+1);
	q=unique(b+1,b+n+1)-b-1;
	build(tr[0].rt,1,q);
	for (int i=1;i<=n;++i)
	{
		p=lower_bound(b+1,b+q+1,a[i])-b;
		tr[i].rt=modify(tr[i-1].rt,1,q);
	}
	while (m--)
	{
		scanf("%d%d%d",&l,&r,&k);
		ans=query(tr[l-1].rt,tr[r].rt,1,q,k);
		printf("%d\n",b[ans]);
	} 
	return 0;
}

FFT

#include <bits/stdc++.h>
const int NR = 1 << 22;
const double eps = 0.49, pi = acos(-1.0);
using namespace std;
complex<double> a[NR];                
int n, m, rev[NR];                  
void FFT(complex<double> *a, int n, int inv)
{
    for (int i = 0; i < n; ++i)
        if (i < rev[i])
            swap(a[i], a[rev[i]]);
    for (int i = 1; i < n; i <<= 1)
    {                              
        complex<double> wn(cos(pi / i), inv * sin(pi / i)); 
        for (int j = 0; j < n; j += (i << 1))   
        {
            complex<double> w0(1, 0);
            for (int k = 0; k < i; ++k, w0 *= wn)
            { //??
                complex<double> x = a[j + k], y = w0 * a[i + j + k];
                a[j + k] = x + y;
                a[i + j + k] = x ## y;
            }
        }
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n; ++i)
    { 
        double x;
        scanf("%lf", &x);
        a[i].real(x);  
    }
    for (int i = 0; i <= m; ++i)
    { 
        double x;
        scanf("%lf", &x);
        a[i].imag(x);
    }
    int len = 1 << max((int)ceil(log2(n + m)), 1); 
    for (int i = 0; i < len; ++i)
        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (max((int)ceil(log2(n + m)), 1) ## 1));
    FFT(a, len, 1);
    for (int i = 0; i <= len; ++i)
        a[i] = a[i] * a[i];       
    FFT(a, len, -1);         
    for (int i = 0; i <= n + m; ++i)     
        printf("%.0f ", a[i].imag() / 2 / len + eps); 
    return 0;
}

KMP

#include<cstdio>
#include<cstring>
#define N 1000005
using namespace std;
int n,m,p[N<<1];
char s[N<<1],s1[N],s2[N];
int main()
{
    scanf("%s",s1+1);scanf("%s",s2+1);
    n=strlen(s1+1);m=strlen(s2+1);
    for (int i=1;i<=m;++i)
        s[i]=s2[i];
    s[m+1]='#';
    for (int i=1;i<=n;++i)
        s[m+i+1]=s1[i];
    for (int i=2;i<=n+m+1;++i)
    {
        int j=p[i-1];
        while (j>0&&s[i]!=s[j+1]) j=p[j];
        if (s[i]==s[j+1]) j++;
        p[i]=j;
    }
    for (int i=m+2;i<=n+m+1;++i)
        if (p[i]==m) printf("%d\n",i-2*m);
    for (int i=1;i<=m;++i)
        printf("%d ",p[i]);
    return 0;
}

Dinic

#include<queue>
#include<cstdio>
#include<cstring>
#define N 205
#define M 5005
#define inf 12345645656879
#define ll long long
using namespace std;
int n,m,s,t,tot=1,dep[N],cur[N];
ll ans;
struct node {int to,next,head;ll flow;}a[M<<1];
queue<int> q;
ll min(ll x,ll y) {return x<y?x:y;}
void add(int x,int y,ll z)
{
    a[++tot].to=y;a[tot].flow=z;a[tot].next=a[x].head;a[x].head=tot;
    a[++tot].to=x;a[tot].flow=0;a[tot].next=a[y].head;a[y].head=tot;
}
bool bfs()
{
    memset(dep,0,sizeof(dep));   
    for (int i=1;i<=n;++i)
        cur[i]=a[i].head;
    dep[s]=1;
    while (!q.empty()) q.pop();
    q.push(s);
    while (!q.empty())
    {
        int x=q.front();q.pop();
        for (int i=a[x].head;i;i=a[i].next)
        {
            int y=a[i].to;ll z=a[i].flow;
            if (z&&!dep[y])
            {
                dep[y]=dep[x]+1;
                q.push(y);
                if (y==t) return true;
            }
        }
    }
    return false;
}
ll dinic(int x,ll f)
{
    if (x==t) return f;
    ll sum=0;
    for (int i=cur[x];i;i=a[i].next)
    {
        cur[x]=i;
        int y=a[i].to;ll z=a[i].flow;
        if (z&&dep[y]==dep[x]+1)
        {
            ll res=dinic(y,min(f,z));
            a[i].flow-=res;a[i^1].flow+=res;
            sum+=res;f-=res;
            if (f<=0) break;
        }
    }
    return sum;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for (int i=1;i<=m;++i)
    {
        int x,y;ll z;
        scanf("%d%d%lld",&x,&y,&z);
        add(x,y,z);
    }
    while (bfs()) ans+=dinic(s,inf);
    printf("%lld\n",ans);
    return 0;
}

线性筛(素数、欧拉数、莫比乌斯函数)

phi[1]=1;
for (int i=2;i<=N;++i)
{
	if (!phi[i]) p[++prt]=i,phi[i]=i-1,mu[i]=-1;
	for (int j=1;j<=prt&&i*p[j]<=N;++j)
	{
		if (i*%pri[j]==0) {phi[i*p[j]]=phi[i]*p[j];mu[i*p[j]]=0;break;}
		phi[i*p[j]]=phi[i]*phi[p[j]];
        mu[i*p[j]]=-mu[i];
	}
}

向量旋转

将一个向量逆时针旋转任意角 \(\theta\),就是乘矩阵 \(\begin{vmatrix}\cos \theta&-\sin \theta\\\sin \theta & \cos \theta\end{vmatrix}\)

posted @ 2023-03-30 21:07  Thunder_S  阅读(2)  评论(0)    收藏  举报