OI模板库

有时间就加一点吧....

Tarjan

缩点

namespace Tarjan{
	int col[N],num[N],dfn[N],low[N],cnt,colornum,val[N];
	bool ins[N];
	stack<int>s;
	vector<int>g[N];
	vector<int>e[N];
	int a[N];
	inline void tarjan(int u){
		dfn[u]=low[u]=++cnt;
		s.push(u);ins[u]=1;
		for(auto v:g[u]){
			if(!dfn[v]){
				tarjan(v);
				low[u]=min(low[u],low[v]);
			}
			else if(ins[v])low[u]=min(low[u],dfn[v]);
		}
		if(dfn[u]==low[u]){
			int t;
			colornum++;
			do{
				t=s.top();s.pop();
				col[t]=colornum;
				num[colornum]++;
				val[colornum]+=a[t];
				ins[t]=0;
			}while(t!=u);
		}
	}
}using namespace Tarjan;

求割点

vector<node>e;
vector<int>g[N];
int dfn[N],low[N],cnt;
int cut[N],rt;
inline void dfs(int u,int from){
	dfn[u]=low[u]=++cnt;
	int son=0;
	for(auto i:g[u]){
		if((i^from)==1)continue;
		int v=e[i].v;
		son++;
		if(!dfn[v]){
			dfs(v,i);
			low[u]=min(low[u],low[v]);
			if(u==rt&&son>1)cut[u]=1;
			else if(u!=rt&&low[v]>=dfn[u])cut[u]=1;
		}
		else low[u]=min(low[u],dfn[v]);
	}
}

求割边

void dfs(int u,int from){
	dfn[u]=low[u]=++idx;
	for(auto [v,e]:g[u]){
		if((e^1)==from)continue;
		if(!dfn[v]){
			dfs(v,e);
			low[u]=min(low[u],low[v]);
			if(low[v]>dfn[u])cutedg[e>>1]=1;
		}
		else low[u]=min(low[u],dfn[v]);
	}
}

关于tarjan的题目,一定要注意重边,不仅是开始的重边,也有缩点之后的重边。

圆方树

void Tarjan(int u) {
  printf("  Enter : #%d\n", u);
  low[u] = dfn[u] = ++dfc;                // low 初始化为当前节点 dfn
  stk[++tp] = u;                          // 加入栈中
  for (int v : G[u]) {                    // 遍历 u 的相邻节点
    if (!dfn[v]) {                        // 如果未访问过
      Tarjan(v);                          // 递归
      low[u] = std::min(low[u], low[v]);  // 未访问的和 low 取 min
      if (low[v] == dfn[u]) {  // 标志着找到一个以 u 为根的点双连通分量
        ++cnt;                 // 增加方点个数
        printf("  Found a New BCC #%d.\n", cnt - N);
        // 将点双中除了 u 的点退栈,并在圆方树中连边
        for (int x = 0; x != v; --tp) {
          x = stk[tp];
          T[cnt].push_back(x);
          T[x].push_back(cnt);
          printf("    BCC #%d has vertex #%d\n", cnt - N, x);
        }
        // 注意 u 自身也要连边(但不退栈)
        T[cnt].push_back(u);
        T[u].push_back(cnt);
        printf("    BCC #%d has vertex #%d\n", cnt - N, u);
      }
    } else
      low[u] = std::min(low[u], dfn[v]);  // 已访问的和 dfn 取 min
  }
  printf("  Exit : #%d : low = %d\n", u, low[u]);
  printf("  Stack:\n    ");
  for (int i = 1; i <= tp; ++i) printf("%d, ", stk[i]);
  puts("");
}

虚树

void add(int u,int v){
		adj[u].push_back(v);
		//adj[v].push_back(u);
	}
	void build(int m){
		
		sort(a.begin(),a.end(),cmp);
		a.push_back(1);
		up(i,0,m-2){
			a.push_back(lca(a[i],a[i+1]));
		}
		sort(a.begin(),a.end(),cmp);
		a.erase(unique(a.begin(),a.end()),a.end());
		int len=a.size();
		t=len;
		for(int i=0;i<len-1;i++){
			int lc=(lca(a[i],a[i+1]));
			add(lc,a[i+1]);
		}

	}

cdq

struct node{
	int a,b,c,w,ans;
}d[500500],a[500500];
int n,m,len;
int ans[500500];
inline bool cmp(node x,node y){
	if(x.a==y.a){
		if(x.b==y.b)return x.c<y.c;
		return x.b<y.b;
	}
	return x.a<y.a;
}
int tr[500500];
inline int lowbit(int x){return x&(-x);}
inline int ask(int i){
	int ans=0; 
	for(;i;i-=lowbit(i))ans+=tr[i];
	return ans;
}
inline void add(int i,int k){
	for(;i<=m;i+=lowbit(i))tr[i]+=k;
}
inline bool cmpy(node u,node v){
    if(u.b==v.b)return u.c<v.c;
    return u.b<v.b;
}
inline void cdq(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1;
    cdq(l,mid);
	cdq(mid+1,r);
    sort(a+l,a+mid+1,cmpy);
    sort(a+mid+1,a+r+1,cmpy);
    int i=mid+1,j=l;
    for(;i<=r;i++){
        while(a[j].b<=a[i].b&& j<=mid)add(a[j].c,a[j].w),j++;
        a[i].ans+=ask(a[i].c);
    }
    for(i=l;i<j;i++)add(a[i].c,-a[i].w);
}
signed main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		d[i].a=read();
		d[i].b=read();
		d[i].c=read();
	}
	sort(d+1,d+1+n,cmp);
	int c=0;
    for(int i=1;i<=n;i++){
        c++;
        if(d[i].a!=d[i+1].a ||d[i].b!=d[i+1].b ||d[i].c!=d[i+1].c){
			a[++len]=d[i];
			a[len].w=c;
			c=0;
		}
    } 
	cdq(1,len); 
    for(int i=1;i<=len;i++)ans[a[i].ans+a[i].w-1]+=a[i].w;
    for(int i=0;i<n;i++)printf("%d\n",ans[i]);
    return 0;
}

树链剖分求LCA

struct treelca{
	int siz[N],son[N],fa[N],dep[N],top[N];
	inline void dfs1(int u,int from){
		siz[u]=1;son[u]=0;
		dep[u]=dep[from]+1;
		for(auto v:g[u]){
			if(v==from) continue;
			fa[v]=u;dfs1(v,u);
			if(siz[v]>siz[son[u]])son[u]=v;
			siz[u]+=siz[v];
		}
	}
	inline void dfs2(int u,int tp){
		top[u]=tp;
		if(son[u]!=0) dfs2(son[u],tp);
		for(auto v:g[u]){
			if(v==fa[u]||v==son[u]) continue;
			dfs2(v,v);
		}
	}
	inline int lca(int x,int y){
		while(top[x]!=top[y]){
			if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
			else y=fa[top[y]];
		}
		return dep[x]<dep[y]?x:y;
	}
}T;

ST表

code

struct ST{
    int dp[N][20],pos[N][20];
    inline void build(int l,int r,int arr[]){
        up(i,l,r)dp[i-l+1][0]=arr[i];
        up(i,l,r)pos[i][0]=i;
        int res=0;
        for(int j=1;(1<<j)<=r-l+1;j++){
            for(int i=l;i+(1<<j)-1<=r;i++){
                int x=pos[i-l+1][j-1],y=pos[i-l+1+(1<<(j-1))][j-1];
                dp[i-l+1][j]=max(dp[i-l+1][j-1],dp[i-l+1+(1<<(j-1))][j-1]);
                pos[i-l+1][j]=arr[x]>arr[y]?x:y;
            }
        }
    }
    inline int ask(int l,int r){
        int k=log2(r-l+1);
        return max(dp[l][k],dp[r-(1<<k)+1][k]);
    }
    inline int askpos(int l,int r,int arr[]){
        int k=log2(r-l+1);
        int x=pos[l][k],y=pos[r-(1<<k)+1][k];
        return arr[x]>arr[y]?x:y;
    }
}T;

快读快出


namespace IO{
	inline int read(){
		char c=getchar();int x=0,fh=0;
        while(c<'0'||c>'9'){fh|=c=='-';c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return fh?-x:x;
	}
	inline void wt(int x){
		if(x<0){x=-x;putchar('-');}
		if(x>9)wt(x/10);
		putchar((x%10)^48);
	}
	inline void write(int x,bool op){
		wt(x);
		putchar(op?'\n':' ');
	}
}using namespace IO;

AC自动机

struct AC_auto{
    int tr[N][26],cnt,ed[N],fail[N];
    inline void insert(char s[]){
        int len=strlen(s+1),p=0;
        up(i,1,len){
            int ch=s[i]-'a';
            if(!tr[p][ch])tr[p][ch]=++cnt;
            p=tr[p][ch];
        }
        ed[p]++;
    }
    queue<int>q;
    inline void getfail(){
        up(i,0,25)if(tr[0][i])q.push(tr[0][i]);
        while(q.size()){
            int u=q.front();q.pop();
            up(i,0,25){
                int v=tr[u][i];
                if(v){
                    fail[v]=tr[fail[u]][i];
                    q.push(v);
                }
                else tr[u][i]=tr[fail[u]][i];
            }
        }
    }
    inline int ask(char s[]){
        int len=strlen(s+1),p=0,ans=0;
        up(i,1,len){
            int ch=s[i]-'a';
            p=tr[p][ch];
            for(int v=p;v&&ed[v]!=-1;v=fail[v])ans+=ed[v],ed[v]=-1;
        }
        return ans;
    }
}T;


Dinic

struct Dinic{
	struct edge{
		int u,v,cap,flow;
	};
	vector<edge>edges;
	vector<int>g[N];
	int cur[N],d[N];
	bool vis[N];
	inline void add(int u,int v,int cap){
		edges.push_back({u,v,cap,0});
		edges.push_back({v,u,0,0});
		int t=edges.size();
		g[u].push_back(t-2);
		g[v].push_back(t-1);
	}
	inline bool bfs(int s,int t){
		memset(vis,0,sizeof vis);
		queue<int>q;
		q.push(s);
		d[s]=0;vis[s]=1;
		while(q.size()){
			int u=q.front();q.pop();
			for(auto i:g[u]){
				auto e=edges[i];
				if(!vis[e.v]&&e.cap>e.flow){
					vis[e.v]=1;
					d[e.v]=d[u]+1;
					q.push(e.v);
				}
			}
		}
		return vis[t];
	}
	inline int dfs(int u,int a,int t){
		if(u==t||a==0)return a;
		int flow=0,f;
		for(int &i=cur[u];i<g[u].size();i++){
			auto& e=edges[g[u][i]];
			if(d[u]+1==d[e.v]&&(f=dfs(e.v,min(a,e.cap-e.flow),t))>0){
				e.flow+=f;
				edges[g[u][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(a==0)break;
			}
		}
		return flow;
	}
	inline int maxflow(int s,int t){
		int flow=0;
		while(bfs(s,t)){
			memset(cur,0,sizeof cur);
			flow+=dfs(s,inf,t);
		}
		return flow;
	}
}E;
struct Dinic{
	struct edge{
        int u,v,cap,flow,w;
    };
    vector<edge>edges;
    vector<int>g[N];
    inline void add(int u,int v,int cap,int w){
        edges.push_back({u,v,cap,0,w});
        edges.push_back({v,u,0,0,-w});
        int t=edges.size();
        g[u].push_back(t-2);
        g[v].push_back(t-1);
    }
    bool vis[N];
    int dis[N],cur[N];
    queue<int>q;
    inline bool spfa(int s,int t){
        memset(dis,0x3f,sizeof dis);
        memset(vis,0,sizeof vis);
        dis[s]=0;vis[s]=1;
        q.push(s);
        while(q.size()){
            int u=q.front();q.pop();
            vis[u]=0;
            for(auto i:g[u]){
                auto [_,v,cap,flow,w]=edges[i];
                if(dis[v]>dis[u]+w&&cap>flow){
                    dis[v]=dis[u]+w;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                        if(dis[q.front()]>dis[q.back()])swap(q.front(),q.back());
                    }
                }
            }
        }
        return dis[t]<inf;
    }
    inline int dfs(int u,int a,int t){
        if(u==t||a==0)return a;
        vis[u]=1;
        int flow=0;
        for(int &i=cur[u];i<g[u].size();i++){
            auto &e=edges[g[u][i]];
            if(!vis[e.v]&&dis[e.v]==dis[u]+e.w&&e.cap>e.flow){
                int res=dfs(e.v,min(a,e.cap-e.flow),t);
                flow+=res;
                e.flow+=res;
                edges[g[u][i]^1].flow-=res;
                a-=res;
                if(a==0)break;
            }
        }
        vis[u]=0;
        return flow;
    }
    inline pii mincostmaxflow(int s,int t){
        int res,flow=0,cost=0;
        while (spfa(s,t)) {
            memset(cur, 0, sizeof(cur));
            while ((res=dfs(s,inf,t)))flow += res,cost += res * dis[t];
        }
        return {flow,cost};
    }
}E;

lucas

inline int ksm(int a,int b){
    int res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
int inv[N],fac[N];
inline void init(){
    inv[0]=fac[0]=1;
    up(i,1,mod+10){
        fac[i]=fac[i-1]*i%mod;
        inv[i]=ksm(fac[i],mod-2);
    }
}
inline int C(int n,int m){
	if(n<m) return 0;
	return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
inline int lucas(int n,int m){
	if(m==0) return 1;
	return (C(n%mod,m%mod)*lucas(n/mod,m/mod))%mod;
}

Z函数

int n,m;
char a[N],b[N];
int z[N],p[N];
signed main() {
	scanf("%s",a+1);
	scanf("%s",b+1);
	int lenb=strlen(b+1);
	z[1]=lenb;
	for(int i=2,l=0,r=0;i<=lenb;i++) {
		z[i]=i>r?0:min(z[i-l+1],r-i+1);
    	while(b[1+z[i]]==b[i+z[i]])z[i]++;
    	if(i+z[i]-1>r)l=i,r=i+z[i]-1;
	}
	int lena=strlen(a+1);
	for(int i=1,l=0,r=0;i<=lena;i++){
		p[i]=i>r?0:min(z[i-l+1],r-i+1);
		while(p[i]<lenb&&b[1+p[i]]==a[i+p[i]])p[i]++;
    	if(i+p[i]-1>r)l=i,r=i+p[i]-1;
	}
	int ans=0;
	up(i,1,lenb)ans^=i*(z[i]+1);
	cout<<ans<<endl;
	ans=0;
	up(i,1,lena)ans^=i*(p[i]+1);
	cout<<ans<<endl;
	return 0;
}

失配树

inline void failtree(){
        dn(i,n,1){
            siz[i]++;
            if(nxt[i])siz[nxt[i]]+=siz[i];
            if(siz[i]>=siz[son[nxt[i]]])son[nxt[i]]=i;
        }
        up(i,1,n){
            dep[i]=dep[nxt[i]]+1;
            if(son[nxt[i]]!= i)top[i] = i;
            else top[i]=top[nxt[i]];
            fa[i]=nxt[i];
        }
 }
bool vis[N];
signed main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    getnxt();
    T.failtree();
    int q=read();
    int l,r;
    while(q--){
        l=nxt[read()];r=nxt[read()];
        write(T.lca(l,r),1);
    }
    return 0;
}

高斯消元

namespace gauss{
	ldb a[500][500];
	int n;
	inline void work(){
		for(int r=1,c=1;c<=n;c++,r++){
			int t=r;
			up(i,r+1,n){
				if(fabs(a[i][c])>fabs(a[t][c]))t=i;
			}
			up(i,c,n+1)swap(a[t][i],a[r][i]);
			if(!a[c][c]){
				puts("No Solution");
				exit(0);
			}
			dn(i,n+1,c)a[r][i]/=a[r][c];
			up(i,r+1,n){
				dn(j,n+1,c){
					a[i][j]-=a[i][c]*a[r][j];
				}
			}
		}
		dn(i,n,2){
			dn(j,i-1,1){
				a[j][n+1]-=a[i][n+1]*a[j][i];
				a[j][i]=0;
			}
		}
	}
	inline void print(){
		up(i,1,n){
			printf("%.3Lf ",a[i][n+1]);
		}
	}
}using namespace gauss;

线性基

namespace Linear_basis{
	int p[100],cnt,flag0=0;
	inline void insert(int x){
		if(x==0)flag0=1;
		dn(i,62,0){
			if(x&(1ll<<i)){
				if(!p[i]){
					p[i]=x;
					cnt++;
					return;
				}
				else x^=p[i];
			}
		}
	}
	inline bool ask(int x){
		dn(i,62,0){
			if(x&(1ll<<i)){
				x^=p[i];
			}
		}
		return x==0;
	}
	inline int askmax(int x) {
		int ans=x;
		dn(i,62,0)if((ans^p[i])>ans)ans^=p[i];
		return ans;
	}
	inline int askmin(int x){
		int ans=x;
		dn(i,62,0)if(ans>(p[i]^ans))ans^=p[i];
		return ans;
	}

}using namespace Linear_basis;

点分治

int n,m;
vector<pii>g[N];
int lim;
bool del[N];
inline int getsiz(int u,int from){
	if(del[u])return 0;
	int res=1;
	for(auto [v,w]:g[u]){
		if(v==from)continue;
		res+=getsiz(v,u);
	}
	return res;
}
inline int getwc(int u,int from,int tot,int&wc){
	if(del[u])return 0;
	int sum=1,maxl=0;
	for(auto [v,w]:g[u]){
		if(v==from)continue;
		int t=getwc(v,u,tot,wc);
		maxl=max(maxl,t);
		sum+=t;
	}
	maxl=max(maxl,tot-sum);
	if(maxl<=tot/2)wc=u;
	return sum;
}
inline void dfs(int u,int from,int dis,vector<int>&q){
	if(del[u])return;
	q.push_back(dis);
	for(auto [v,w]:g[u]){
		if(v==from)continue;
		dfs(v,u,dis+w,q);
	}
}
inline int get(vector<int>&a){
	sort(a.begin(),a.end());
	int res=0,len=a.size();
	for(int i=len-1,j=-1;i>=0;i--){
		while(j+1<i&&a[j+1]+a[i]<=lim)j++;
		j=min(j,i-1);
		res+=j+1;
	}
	return res;
}
inline int clac(int u){
	if(del[u])return 0;
	int res=0;
	getwc(u,0,getsiz(u,0),u);
	del[u]=1;
	vector<int>p;
	for(auto [v,w]:g[u]){
		if(del[v])continue;
		vector<int>q;
		dfs(v,u,w,q);
		res-=get(q);
		for(auto x:q){
			p.push_back(x);
			if(x<=lim)res++;
		} 
	}
	res+=get(p);
	for(auto [v,w]:g[u])res+=clac(v);
	return res;
}

李超线段树

int n,last;
struct line{
    ldb k,b;
}p[N];
int cnt;
inline void add(int x0, int y0, int x1, int y1) {
    cnt++;
    if(x0==x1)p[cnt].k=0,p[cnt].b=max(y0, y1);
    else p[cnt].k=1.0*(y1-y0)/(x1-x0),p[cnt].b=y0-p[cnt].k*x0;
}
int s[N];
inline ldb calc(int id,int d) { return p[id].b+p[id].k*d;}
inline int cmp(ldb x,ldb y) {
    if(x-y>eps)return 1;
    if(y-x>eps)return -1;
    return 0;
}
inline void change(int k,int l,int r,int u){
    int &v=s[k],mid=(l+r)>>1;
    int bmid=cmp(calc(u,mid),calc(v,mid));
    if(bmid==1||(!bmid&&u<v))swap(u,v);
    int bl=cmp(calc(u,l),calc(v,l)),br=cmp(calc(u,r),calc(v,r));
    if(bl==1||(!bl&&u<v))change(lc,l,mid,u);
    if(br==1||(!br&&u<v))change(rc,mid+1,r,u);
}
inline void insert(int k,int tl,int tr,int l,int r,int u){
    if(l<=tl&&tr<=r) {
        change(k,tl,tr,u);
        return;
    }
    int mid=(tl+tr)>>1;
    if(l<=mid)insert(lc,tl,mid,l,r,u);
    if(mid<r)insert(rc,mid+1,tr,l,r,u);
}
inline pdi pmax(pdi x,pdi y){
    if(cmp(x.fi,y.fi)==-1)return y;
    else if(cmp(x.fi,y.fi)==1)return x;
    return x.se<y.se?x:y;
}
inline pdi ask(int k,int l,int r,int d){
    if (r<d||d<l)return {0,0};
    int mid=(l+r)>>1;
    db res=calc(s[k],d);
    if(l==r)return{res,s[k]};
    return pmax({res,s[k]},pmax(ask(lc,l,mid,d),ask(rc,mid+1,r,d)));
}
signed main(){
    n=read();
    int op,k,x0,y0,x1,y1;
    up(i,1,n){
        op=read();
        if(op==1){
            x0=(read()+last-1+mod1)%mod1+1;
            y0=(read()+last-1+mod2)%mod2+1;
            x1=(read()+last-1+mod1)%mod1+1;
            y1=(read()+last-1+mod2)%mod2+1;
            if (x0>x1)swap(x0,x1),swap(y0,y1);
            add(x0,y0,x1,y1);
            insert(1,1,mod1,x0,x1,cnt);
        }
        else {
            k=read();
            k=(k+last-1+mod1)%mod1+1;
            last=ask(1,1,mod1,k).second;
            cout<<(last)<<endl;
        }
    }
    return 0;
}
posted @ 2023-10-25 18:36  LiQXing  阅读(73)  评论(0)    收藏  举报