operator_的模板综合(动态更新)

last update :2023/10/13

模板综合

卡常

1.快读

inline int read() {
	int s=0,m=0;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
	while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return m?-s:s;
}

2.快输

inline void write(int x) {
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x-x/10*10+'0');
}

高精度

struct BIG {//不支持负数 
	int num[],len;//从1到len倒序存储
	BIG() {
		memset(num,0,sizeof(num));
		len=0;
	}
	BIG operator +(const BIG &x) {
		BIG ans;int u=0;
		ans.len=max(len,x.len);
		for(int i=1;i<=ans.len;i++) {
			ans.num[i]=(num[i]+x.num[i]+u)%10;
			u=(num[i]+x.num[i]+u)/10;
		}
		if(u!=0)
			ans.num[++ans.len]=u;
		return ans;
	}
	BIG operator -(const BIG &x) {
		BIG ans;int u=0;
		ans.len=len;
		for(int i=1;i<=ans.len;i++) {
			ans.num[i]=(num[i]-x.num[i]-u+10)%10;
			u=(num[i]-u<x.num[i]);
		}
		while(ans.num[ans.len]==0&&ans.len>1)
			ans.len--;
		return ans;
	}
	BIG operator *(const BIG &x) {
		BIG ans;int u=0;
		ans.len=len+x.len-1;
		for(int i=1;i<=len;i++)
			for(int j=1;j<=x.len;j++)
				ans.num[i+j-1]+=num[i]*x.num[j];
		for(int i=1;i<=ans.len;i++) {
			ans.num[i]=ans.num[i]+u;
			u=ans.num[i]/10,ans.num[i]%=10;
		}
		for(;u;u/=10)
			ans.num[++ans.len]=u%10;
		return ans;
	} 
	BIG operator /(const int &x) {
		BIG ans;int u=0;
		ans.len=len;
		for(int i=ans.len;i;i--) {
			ans.num[i]=(u*10+num[i])/x;
			u=(u*10+num[i])%x;
		}
		while(ans.num[ans.len]==0&&ans.len>1)
			ans.len--;
		return ans;
	} 
	int operator %(const int &x) {
		int u=0;
		for(int i=len;i;i--) 
			u=(u*10+num[i])%x;
		return u;
	}
};
BIG int_big(int a) {
	BIG ans;
	for(int i=a;i;i/=10)
		ans.num[++ans.len]=a%10;
	return ans;
}
BIG str_big(string s) {
	BIG ans;
	for(int i=s.size()-1;i>=0;i--)
		ans.num[++ans.len]=s[i]-'0';
	return ans;
}
string big_str(BIG a) {
	string s="";
	for(int i=1;i<=a.len;i++)
		s=s+char(a.num[i]+'0');
	return s;
}
BIG read() {
	string s;
	cin>>s;
	return str_big(s);
}
void print(BIG a) {
	for(int i=a.len;i;i--)
		cout<<a.num[i];
	putchar('\n');
}

字符串

1.KMP匹配

int nxt[];
void get(char t[]) {
	nxt[1]=0;
	for(int i=2,j=0;i<=strlen(t+1);i++) {
		while(j&&t[i]!=t[j+1])
			j=nxt[j];
		if(t[i]==t[j+1])
			j++;
		nxt[i]=j;
	}
}
int kmp(char s[],char t[]) {
	get(t);
	for(int i=1,j=0;i<=strlen(s+1);i++) {
		while(j&&s[i]!=t[j+1])
			j=nxt[j];
		if(s[i]==t[j+1])
			j++;
		if(j==strlen(t+1))
			return i-j+1;
	}
	return -1;
}

2.Manacher

char str[],tmp[];
int p[];
char* add(char* s) {
	int cnt=0,l=strlen(s);
	tmp[0]='(',tmp[++cnt]='$';
	for(int i=0;i<l;i++)
		tmp[++cnt]=s[i],tmp[++cnt]='$';
	tmp[++cnt]=')';
	return tmp;
}
int manacher(char* s) {
	int ans=0,r=0,mid=0,l=strlen(s);
	for(int i=1;i<l-1;i++) {
		p[i]=(r>=i?min(p[2*mid-i],r-i):1);
		while(s[i+p[i]]==s[i-p[i]])
			p[i]++;
		if(i+p[i]>r)
			r=i+p[i],mid=i;
		ans=max(ans,p[i]);
	}
	return ans-1;
}

3.后缀数组

int n,m,sa[],rk[],height[],t[];
int x[],y[];
void get_sa(char s[]) {
	n=strlen(s+1),m=266;
	for(int i=1;i<=n;i++) t[x[i]=s[i]]++;
	for(int i=2;i<=m;i++) t[i]+=t[i-1];
	for(int i=n;i;i--) sa[t[x[i]]--]=i;
	for(int k=1,cnt=0;k<=n;k*=2) {
		cnt=0;
		for(int i=n-k+1;i<=n;i++) y[++cnt]=i;
		for(int i=1;i<=n;i++) if(sa[i]>k) y[++cnt]=sa[i]-k;
		memset(t,0,sizeof(t));
		for(int i=1;i<=n;i++) t[x[i]]++;
		for(int i=2;i<=m;i++) t[i]+=t[i-1];
		for(int i=n;i;i--) sa[t[x[y[i]]]--]=y[i],y[i]=0;
		swap(x,y);x[sa[1]]=cnt=1;
		for(int i=2;i<=n;i++)
			cnt+=(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]),x[sa[i]]=cnt;
		if(cnt==n) break;
		m=cnt;
	}
	for(int i=1;i<=n;i++) rk[sa[i]]=i;
	for(int i=1,k=0;i<=n;i++) {
		if(rk[i]==1) continue;
		k=max(0,k-1);int j=sa[rk[i]-1];
		while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;
		height[rk[i]]=k;
	}
}

数论

1.(拓展)欧几里得算法

int exgcd(int a,int b,int& x,int& y) {
	if(!b) {x=1,y=0;return a;}
	int d=exgcd(b,a%b,y,x);
	y=y-a/b*x;
	return d;
}

2.快速乘

int qmul(int x,int y,int mod) {
	int s=0;
	while(y) {
		if(y&1) s=(s+x)%mod;
		x=x*2%mod,y>>=1;
	}
	return s;
}

3.快速幂

int qpow(int x,int y,int mod=M) {
	int s=1;
	while(y) {
		if(y&1) s=(s*x)%mod;
		x=x*x%mod,y>>=1;
	}
	return s;
}

4.(拓展)中国剩余定理

int n,a,b,a0,b0;
void merge(int a1,int b1,int a2,int b2) {
	int x,y;
	int d=exgcd(a1,a2,x,y);
	x=x*((b2-b1)/d)%(a2/d);
	if(x<0) x+=a2/d;
	a=a1/d*a2;
	b=(a1*x+b1)%a;
	if(b<0) b+=a;
}

5.欧拉函数

直接求解
int phi(int n) {
	int ans=n;
	for(int i=2;i*i<=n;i++) if(n%i==0) {
		ans=ans/i*(i-1);
		while(n%i==0) n/=i;
	}
	if(n>1) ans=ans/n*(n-1);
	return ans;
}
预处理(即线性筛)
int p[],phi[],v[],cnt;
void init(int n) {
	phi[1]=1;
	for(int i=2;i<=n;i++) {
		if(!v[i]) p[++cnt]=i,phi[i]=i-1;
		for(int j=1;j<=cnt&&i*p[j]<=n;j++) {
			v[i*p[j]]=1;
			if(i%p[j]==0) {
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
			else phi[i*p[j]]=phi[i]*phi[p[j]];
		}
	}
}

6.FFT

int rv[];
void init(int k) {
	for(int i=0;i<(1<<k);i++)
		rv[i]=(rv[i>>1]>>1)|((i&1)<<(k-1));
}
#define cp complex<double>
void fft(cp a[],int n,int fl) { 
    for(int i=0;i<n;i++)
		if(i<rv[i]) swap(a[i],a[rv[i]]);
	for(int i=1;i<n;i*=2) {
		cp wi=exp(cp(0,fl*pi/i));
		for(int j=0;j<n;j+=i*2) {
			cp w(1,0);
			for(int k=j;k<i+j;k++,w*=wi) {
				cp x=a[k],y=w*a[k+i];
				a[k]=x+y,a[k+i]=x-y;
			}
		}
	}
	if(fl==-1) for(int i=0;i<n;i++) a[i]/=n;
}

7.NTT

int rv[];
void init(int k) {
	for(int i=0;i<(1<<k);i++)
		rv[i]=(rv[i>>1]>>1)|((i&1)<<(k-1));
}
void ntt(int a[],int n,int fl) { 
    for(int i=0;i<n;i++)
		if(i<rv[i]) swap(a[i],a[rv[i]]);
	int ginv=qpow(gt,M-2);
	for(int i=1;i<n;i*=2) {
		int gi=qpow((fl==1?gt:ginv),(M-1)/i/2);
		for(int j=0;j<n;j+=i*2) {
			int g=1;
			for(int k=j,g=1;k<i+j;k++,g=g*gi%M) {
				int x=a[k],y=g*a[k+i]%M;
				a[k]=(x+y)%M,a[k+i]=(x-y+M)%M;
			}
		}
	}
	int ninv=qpow(n,M-2);
	if(fl==-1) for(int i=0;i<n;i++) a[i]=a[i]*ninv%M;
}

图论

结构体式链式前向星

int h[],cnt;
struct QWQ{int v,w,nxt;} e[*2];
void add(int u,int v,int w) {e[++cnt]={v,w,h[u]},h[u]=cnt;}

最短路

1.SPFA
int d[],vis[];
queue<int> q; 
void SPFA(int start) {
	while(q.size()) q.pop();
	memset(d,0x3f,sizeof(d));
  	memset(vis,0,sizeof(vis));
  	d[start]=0,vis[start]=1,q.push(start);
	while(q.size()) {
		int u=q.front();q.pop();
		vis[u]=0;
		for(int i=h[u];i;i=e[i].nxt) {
            int v=e[i].v,w=e[i].w;
            if(d[v]>d[u]+w) {
                if(!vis[v]) q.push(v),vis[v]=1;
                d[v]=d[u]+w;
            }
        }
	}
}
2.dijkstra
int d[],vis[];
struct Node {
	int to,len;
	bool operator<(const Node& x) const{return len>x.len;}
};
priority_queue<Node> pq;
void dijkstra(int start) {
    while(pq.size()) pq.pop();
    memset(d,0x3f,sizeof(d));
    memset(vis,0,sizeof(vis));
	d[start]=0,pq.push({start,0});
	while(pq.size()) {
		int u=pq.top().to;pq.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=h[u];i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			if(d[v]>d[u]+w) {
				d[v]=d[u]+w;
                if(!vis[v]) pq.push({v,d[v]});
			}
		}
	}
}
3.floyd

拓扑序

int in[];
queue<int> q;
void topo() {
	while(!q.empty()) {
		int u=q.front();
		q.pop();
		for(int i=h[u];i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			in[v]--;
			if(in[v]==0) q.push(v);
		}
	}
}

最小生成树

1.kruskal
int f[];
struct qwq{int u,v,w;} e1[];//输入时存储
bool cmp(qwq& x,qwq& y) {return x.w<y.w;}
void init(int n) {for(int i=1;i<=n;i++) f[i]=i;}
int find(int x) {return (f[x]==x?x:f[x]=find(f[x]));}
void merge(int x,int y) {f[find(x)]=find(y);}
void kruskal() {
	init(n);
	sort(e1+1,e1+m+1,cmp);
	for(int i=1;i<=m;i++) {
		int u=e1[i].u,v=e1[i].v,w=e1[i].w;
		if(find(u)!=find(v))
			merge(u,v);
	}
}
2.prim
bool vis[];
int d[];
void prim() {
	memset(d,0x3f,sizeof(d));
	d[1]=0;
	for(int k=1;k<=n;k++) {
		int u=0,minn=1e9;
		for(int i=1;i<=n;i++)
			if(vis[i]==0&&d[i]<minn)
				u=i,minn=d[i];
		vis[u]=1;
		for(int i=h[u];i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			if(vis[v]==0)
				d[v]=min(d[v],w);
		}
	}
}

tarjan

stack<int> st;
int f[],dfn[],low[],cnt,k,scc[];
void tarjan(int u,int fa) {
	st.push(u);
	f[u]=1,dfn[u]=low[u]=++cnt;
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		if(!dfn[v]) {
			tarjan(v,u),low[u]=min(low[u],low[v]);
			if((u==fa&&num>1)||(u!=fa&&dfn[u]<=low[v])) //u是割点
			if(dfn[u]<low[v]) //u-v是割边
		}
		else if(f[v])
			low[u]=min(low[u],dfn[v]);
	}
	if(dfn[u]==low[u]) {
		k++;
		while(1) {
			int top=st.top();st.pop();
			scc[top]=k,f[top]=0;//top在强连通分量k中 
			if(top==u) break;
		}
	}
} 

树链剖分

int d[],fa[],sz[],son[],id[],tot,top[];
void dfs1(int u,int p) {
	fa[u]=p,d[u]=d[p]+1,sz[u]=1;
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		if(v==p) continue;
		dfs1(v,u);sz[u]+=sz[v];
		if(sz[v]>=sz[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int tt) {
	id[u]=++tot,aa[tot]=a[u],top[u]=tt;
	if(!son[u]) return;
	dfs2(son[u],tt);
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		if(v==fa[u]||v==son[u]) continue;
		dfs2(v,v);
	}
}
void jump(int x,int y) {
	while(top[x]!=top[y]) {
		if(d[top[x]]<d[top[y]]) swap(x,y);
		/*(id[top[x]],id[x])*/
		x=fa[top[x]];
	}
	if(d[x]>d[y]) swap(x,y);
	/*(id[x],id[y])*/
}

LCA

1.倍增
int d[],lg[],fa[][25];
void init(int n) {for(int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);}
void dfs(int u,int p) {
	d[u]=d[p]+1,fa[u][0]=p;
	for(int i=1;(1<<i)<=d[u];i++) fa[u][i]=fa[fa[u][i-1]][i-1];
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		if(v==p) continue;
		dfs(v,u);
	}
}
int lca(int x,int y) {
	if(d[x]<d[y]) swap(x,y);
	while(d[x]>d[y]) x=fa[x][lg[d[x]-d[y]]-1];
	if(x==y) return x;
	for(int k=lg[d[x]];k>=0;k--) if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
	return fa[x][0];
}
2.欧拉序
int d[],st[*2][25],id[],len;
void dfs(int u,int p) {
	d[u]=d[p]+1,id[u]=++len,st[len][0]=u;
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		if(!id[v]) {
			dfs(v,u);
			st[++len][0]=u;
		}
	}
}
void init() {
    for(int j=1;(1<<j)<=len;j++)
		for(int i=1;i+(1<<j)-1<=len;i++)
			st[i][j]=cmp(st[i][j-1],st[i+(1<<j-1)][j-1]);
}
int cmp(int a,int b) {return d[a]<d[b]?a:b;}
int query(int l,int r) {
	int k=log2(r-l+1);
	return cmp(st[l][k],st[r-(1<<k)+1][k]);
}
int lca(int x,int y) {return query(min(id[x],id[y]),max(id[x],id[y]));}
3.tarjan(离线)
int n,m,vis[],f[];
map<pair<int,int>,int> ans;//存答案 
vector<int> t[];//输入时存储
void init(int n) {for(int i=1;i<=n;i++) f[i]=i;}
int find(int x) {return (f[x]==x?x:f[x]=find(f[x]));}
void merge(int x,int y) {f[find(x)]=find(y);}
void tarjan(int u) {
	vis[u]=1;
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		tarjan(v);marge(v,u);
	}
	for(int i=0;i<t[u].size();i++) if(vis[y[u][i]]) 
		ans[make_pair(u,t[u][i])]=ans[make_pair(t[u][i],u)]=find(t[u][i]);
}
4.树链剖分
int d[],fa[],sz[],son[],id[],tot,top[];
void dfs1(int u,int p) {
	fa[u]=p,d[u]=d[p]+1,sz[u]=1;
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		if(v==p) continue;
		dfs1(v,u);sz[u]+=sz[v];
		if(sz[v]>=sz[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int tt) {
	id[u]=++tot,top[u]=tt;
	if(!son[u]) return;
	dfs2(son[u],tt);
	for(int i=h[u];i;i=e[i].nxt) {
		int v=e[i].v;
		if(v==fa[u]||v==son[u]) continue;
		dfs2(v,v);
	}
}
int lca(int x,int y) {
	while(top[x]!=top[y]) {
		if(d[top[x]]<d[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	if(d[x]>d[y]) swap(x,y);
	return x;
}

最大流

1.EK
最大流
int g[][];
int flo[],pre[];
queue<int> q;
int bfs(int s,int t) {
	while(q.size()) q.pop();
	memset(flo,0,sizeof(flo));
	memset(pre,0,sizeof(pre));
	q.push(s),flo[s]=INT_MAX;
	while(q.size()) {
		int u=q.front();q.pop();
		if(u==t) return flo[t];
		for(int v=1;v<=n;v++) {
			if(!g[u][v]||pre[v]) continue;
			flo[v]=min(flo[u],g[u][v]);
			q.push(v),pre[v]=u;
		}
	}
	return -1;
}
int EK(int s,int t) {
	int p,maxflow=0;
	while((p=bfs(s,t))!=-1) {
		for(int i=t;i!=s;i=pre[i])
			g[pre[i]][i]-=p,g[i][pre[i]]+=p;
		maxflow+=p;
	}
	return maxflow;
}
最小费用最大流
int flo[],pre[],dis[],vis[],l[];
queue<int> q;
int SPFA(int s,int t) {
	while(q.size()) q.pop();
	memset(flo,0,sizeof(flo));
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	q.push(s),flo[s]=INT_MAX,dis[s]=0,vis[s]=1;
	while(q.size()) {
		int u=q.front();q.pop();
		vis[u]=0;
		for(int i=h[u];i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w,c=e[i].c;
			if(!w||dis[v]<=dis[u]+c) continue;
			if(!vis[v]) q.push(v),vis[v]=1;
			flo[v]=min(flo[u],w),pre[v]=u,dis[v]=dis[u]+c,l[v]=i;
		}
	}
	return (dis[t]>(int)1e9?-1:flo[t]);
}
int maxflow,mincost;
void EK(int s,int t) {
	int p;
	while((p=SPFA(s,t))!=-1) {
		for(int i=t;i!=s;i=pre[i]) {
			int r=l[i];
			e[r].w-=p,e[r^1].w+=p;
		}
		maxflow+=p;
		mincost+=p*dis[t];
	}
}
2.Dinic
int d[],cur[];
queue<int> q;
bool bfs(int s,int t) {
	memset(d,0x3f,sizeof(d));
	memcpy(cur,h,sizeof(h));
	while(q.size()) q.pop();
	q.push(s);d[s]=0;
	while(q.size()) {
		int u=q.front();q.pop();
		for(int i=h[u];i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			if(!w||d[v]<(int)1e9) continue;
			q.push(v);
			d[v]=d[u]+1;
			if(v==t) return 1;
		}
	}
	return 0;
}
int dfs(int u,int sum) {
	if(u==t) return sum;
	int k,res=0;
	for(int& i=cur[u];i;i=e[i].nxt) {
		int v=e[i].v,w=e[i].w;cur[u]=i;
		if(!w||d[v]!=d[u]+1) continue;
		int k=dfs(v,min(sum,w));
		e[i].w-=k,e[i^1].w+=k;
		sum-=k,res+=k;
	}
	return res;
}
int Dinic(int s,int t) {
	int maxflow=0;
	while(bfs(s,t)) maxflow+=dfs(s,INT_MAX);
	return maxflow;
}
3.ISAP
int cur[],d[],pre[],fa[],gap[];
int ISAP(int s,int t) {
	memset(d,0,sizeof(d));
	memset(gap,0,sizeof(gap));
	memset(pre,0,sizeof(pre));
	memset(fa,0,sizeof(fa));
	memcpy(cur,h,sizeof(h));
	gap[0]=n;
	int u=s,maxflow=0,flag=0;
	while(d[s]<n) {
		if(u==t) {
			int flow=INT_MAX;
			for(;u!=s;u=fa[u])
				flow=min(flow,e[pre[u]].w);
			for(u=t;u!=s;u=fa[u])
				e[pre[u]].w-=flow,e[pre[u]^1].w+=flow;
			maxflow+=flow;
		}
		flag=0;
		for(int i=cur[u];i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			if(!w||d[u]!=d[v]+1) continue;
			flag=1,cur[u]=i;
			pre[v]=i,fa[v]=u,u=v;
			break;
		}
		if(flag) continue;
		int minn=n-1;
		for(int i=h[u];i;i=e[i].nxt) 
			if(e[i].w)
				minn=min(minn,d[e[i].v]);
		cur[u]=h[u];
		if(!(--gap[d[u]])) break;
		gap[(d[u]=minn+1)]++;
		if(u!=s) u=fa[u];
	}
	return maxflow;
}

数据结构

1.单调队列

int q[],h=1,t;
void solve(int n,int a[]) {
	for(int i=1;i<=n;i++) {
		while(h<=t&&i-q[h]>=k) h++;
		while(h<=t&&a[q[t]]>a[i]) t--;
		q[++t]=i;
		if(i>=k) //a[q[h]]是[i-k+1,k]中优先级最高的 
	}
}

2.单调栈

int st[],t;
void solve(int n,int a[]) {
	for(int i=1;i<=n;i++) {
		while(t!=0&&a[st[t]]>a[i]) //i是st[t]后第一个优先级比a[st[t]]高的
		st[++t]=i;
	}
}

3.ST表

struct Sparse_Table {
	int st[][25];
	int op(int t1,int t2) {return max(t1,t2);}//RMQ的操作
	void init(int n,int v[]) {
		for(int i=1;i<=n;i++) st[i][0]=v[i];
		for(int j=1;(1<<j)<=n;j++)
			for(int i=1;i+(1<<j)-1<=n;i++)
				st[i][j]=op(st[i][j-1],st[i+(1<<j-1)][j-1]);
	}
	int query(int l,int r) {
	    int k=log2(r-l+1);
	    return op(st[l][k],st[r-(1<<k)+1][k]);
	}
};

4.珂朵莉树

struct Node {
	int l,r;
	mutable int v;
	QWQ() {l=0,r=-1,v=0;}
	bool operator <(const QWQ &a) const{return l<a.l;}
};
struct Old_Driver_Tree {
	set<Node> s;
	IT spilt(int pos) {
		IT it=s.lower_bound((QWQ){pos,0,0});
		if(it!=s.end()&&it->l==pos) return it;
		--it;
		int l=it->l,r=it->r,v=it->v;
		s.erase(it);
		s.insert((QWQ){l,pos-1,v});
		return s.insert((QWQ){pos,r,v}).first;
	}
	void assign(int l,int r,int v) {//区间推平	
		IT itr=spilt(r+1),itl=spilt(l);
		s.erase(itl,itr);
		s.insert((QWQ){l,r,v});
	}
};

5.树状数组

struct Binary_Indexed_Tree {
	int t[];
	int lb(int x) {return x&-x;}
	void build() {//建树
	    for(int i=1;i<=n;++i) {
	        t[i]+=a[i];
	        if(i+lb(i)<=n) t[i+lb(i)]+=t[i];
	    }
	}
	int sum(int x) {int s=0;for(int i=x;i;i-=lb(i)) s+=t[i];return s;}
	int query(int x,int y) {return sum(y)-sum(x-1);}
	void add(int x,int k) {for(int i=x;i<=n;i+=lb(i)) t[i]+=k;}
};

6.线段树

普通
struct Node {int l,r,d,laz;};
struct Segment_Tree {
  	Node t[4*];
	int ls(int p) {return p<<1;}
	int rs(int p) {return p<<1|1;}
	void pushup(int p) {t[p].d=t[ls(p)].d+t[rs(p)].d;}
	void pushdown(int p) {
		t[ls(p)].d+=t[p].laz*(t[ls(p)].r-t[ls(p)].l+1);
		t[rs(p)].d+=t[p].laz*(t[rs(p)].r-t[rs(p)].l+1);
		t[ls(p)].laz+=t[p].laz,t[rs(p)].laz+=t[p].laz;
		t[p].laz=0;
	}
	void build(int p,int l,int r) {//建树
		t[p].l=l,t[p].r=r;
		if(l==r) {t[p].d=a[l];return;}
		int m=(l+r)>>1;
		build(ls(p),l,m);build(rs(p),m+1,r);
		pushup(p);
	}
	void update(int p,int l,int r,int v) {//区间修改
		if(l<=t[p].l&&t[p].r<=r) {
			t[p].d+=(t[p].r-t[p].l+1)*v,t[p].laz+=v;
			return;
		}
		pushdown(p);
		int m=(t[p].l+t[p].r)>>1;
		if(l<=m) update(ls(p),l,r,v);
		if(r>m) update(rs(p),l,r,v);
		pushup(p);
	}
	int query(int p,int l,int r) {//区间询问
		if(l<=t[p].l&&t[p].r<=r) return t[p].d;
		pushdown(p);
		int s=0,m=(t[p].l+t[p].r)>>1;
		if(l<=m) s+=query(ls(p),l,r);
		if(r>m) s+=query(rs(p),l,r);
		return s;
	}
};
动态开点
struct Node {int lf,rt,d,laz;};
struct Segment_Tree {
	int root,tot;
  	QWQ t[2*];
	void pushup(int p) {t[p].d=t[t[p].lf].d+t[t[p].rt].d;}
	void pushtag(int &p,int l,int r,int k) {
		if(!p) p=++tot;
		t[p].d+=(r-l+1)*k,t[p].laz+=k;
	}
	void pushdown(int p,int l,int r) {
		int mid=(l+r)>>1;
		pushtag(t[p].lf,l,mid,t[p].laz);
		pushtag(t[p].rt,mid+1,r,t[p].laz);
		t[p].laz=0;
	}
	void build(int &p,int l,int r) {//建树
		if(!p) p=++tot;
		if(l==r) {t[p].d=a[l];return;}
		int mid=(l+r)>>1;
		build(t[p].lf,l,mid);build(t[p].rt,mid+1,r);
		pushup(p);
	}
	void update(int &p,int l,int r,int nl,int nr,int v) {//区间修改
		if(!p) p=++tot;
		if(nl<=l&&nr>=r) {pushtag(p,l,r,v);return;}
		pushdown(p,l,r);
		int mid=(l+r)>>1;
		if(nl<=mid) update(t[p].lf,l,mid,nl,nr,v);
		if(nr>mid) update(t[p].rt,mid+1,r,nl,nr,v);
		pushup(p);
	}
	int query(int p,int l,int r,int nl,int nr) {//区间询问
		if(nl<=l&&nr>=r) return t[p].d;
		pushdown(p,l,r);
		int mid=(l+r)>>1,res=0;
		if(nl<=mid) res+=query(t[p].lf,l,mid,nl,nr);
		if(nr>mid) res+=query(t[p].rt,mid+1,r,nl,nr);
		return res;
	}
};
李超线段树
const double eps=1e-9;
struct Line {
	int l,r,id;double k,b;
	double f(double x) {return k*x+b;}
} a[400005];
int cnt;
struct Node {int l,r,fl;Line val;};
struct LiChao_Segment_Tree {
  	Node t[4*400005];
	int ls(int p) {return p<<1;}
	int rs(int p) {return p<<1|1;}
	void build(int p,int l,int r) {//建树
		t[p].l=l,t[p].r=r;
		if(l==r) return;
		int m=(l+r)>>1;
		build(ls(p),l,m);build(rs(p),m+1,r);
	}
	int cmp(double a,double b) {return (a-b>eps?1:(b-a>eps?-1:0));}
	void update(int p,Line v) {//区间修改
		if(v.l<=t[p].l&&t[p].r<=v.r) {
			if(!t[p].fl) t[p].fl=1,t[p].val=v;	
			else {
				Line &u=t[p].val;
				int mid=(t[p].l+t[p].r)>>1;
				int bm=cmp(v.f(mid),u.f(mid));
				if(bm==1||(bm==0&&v.id<u.id)) swap(u,v);
				int bl=cmp(v.f(t[p].l),u.f(t[p].l)),br=cmp(v.f(t[p].r),u.f(t[p].r));
				if(bl==1||(bl==0&&v.id<u.id)) update(ls(p),v);
				if(br==1||(br==0&&v.id<u.id)) update(rs(p),v);
			}
			return;
		}
		int m=(t[p].l+t[p].r)>>1;
		if(v.l<=m) update(ls(p),v);
		if(v.r>m) update(rs(p),v);
	}
	Line query(int p,int x) {//区间询问
		if(t[p].l==t[p].r) return t[p].val;
		Line s=t[p].val;int m=(t[p].l+t[p].r)>>1;
		if(x<=m) {
			Line u=query(ls(p),x);
			if(s.f(x)<u.f(x)||(fabs(s.f(x)-u.f(x))<eps&&s.id>u.id)) return u;
			return s;
		}
		else {
			Line u=query(rs(p),x);
			if(s.f(x)<u.f(x)||(fabs(s.f(x)-u.f(x))<eps&&s.id>u.id)) return u;
			return s;
		}
		return s;
	}
};

7.莫队

struct Query {int l,r,id;} p[];
int a[],cnt[],ans[],num;
bool cmp(QWQ a,QWQ b) {return (a.l/num)!=(b.l/num)?a.l<b.l:((a.l/num)&1)?a.r<b.r:a.r>b.r;}
void add(int i) {cur+=(cnt[a[i]]++==0);}
void det(int i) {cur-=(--cnt[a[i]]==0);}
void solve() {
	num=(int)sqrt(n);
	sort(p+1,p+m+1,cmp);
	for(int i=1;i<=m;i++){
		while(l<p[i].l) det(l++);
		while(r<p[i].r) add(++r);
		while(l>p[i].l) add(--l);
		while(r>p[i].r) det(r--);
		ans[p[i].id]=cur;
	}
}

8.treap

旋转
struct Rotate_Treap {
	int l[],r[],v[],rnk[],s[],w[],sz,ans,rt;
	void pushup(int x) {s[x]=s[l[x]]+s[r[x]]+w[x];}
	void lrotate(int &k) {
		int t=r[k];
		r[k]=l[t],l[t]=k,s[t]=s[k],pushup(k),k=t;
	}
	void rrotate(int &k) {
		int t=l[k];
		l[k]=r[t],r[t]=k,s[t]=s[k],pushup(k),k=t;
	}
	void insert(int &k,int x) {//单点插入 
		if(!k) {
			k=++sz,s[k]=1,w[k]=1,v[k]=x,rnk[k]=rand();
			return;
		}
		s[k]++;
		if(v[k]==x) w[k]++;
		if(v[k]<x) {
			insert(r[k],x);
			if(rnk[r[k]]<rnk[k]) lrotate(k);
		} 
		if(v[k]>x) {
			insert(l[k],x);
		    if(rnk[l[k]]<rnk[k]) rrotate(k);
        }
	}
	bool del(int &k,int x) {//单点删除 
		if(!k) return false;
		if(v[k]==x) {
			if(w[k]>1) {w[k]--,s[k]--;return true;}
			if(l[k]==0||r[k]==0) {k=l[k]+r[k];return true;} 
			else if(rnk[l[k]]<rnk[r[k]]) {rrotate(k);return del(k,x);} 
			else {lrotate(k);return del(k,x);}
		} 
		else if(v[k]<x) {
			bool succ=del(r[k],x);
			if(succ) s[k]--;return succ;
		} 
		else {
			bool succ=del(l[k],x);
			if(succ) s[k]--;return succ;
		}
	}
	int queryrank(int k,int x) {//单点查询排名 
		if(!k) return 0;
		if(v[k]==x) return s[l[k]]+1;
		else if(x>v[k]) return s[l[k]]+w[k]+queryrank(r[k],x);
		else return queryrank(l[k],x);
	}
	int querynum(int k,int x) {//单点查询数值 
		if(!k) return 0;
		if(x<=s[l[k]]) return querynum(l[k],x);
		else if(x>s[l[k]]+w[k]) return querynum(r[k],x-s[l[k]]-w[k]);
		else return v[k];
	}
	void querypre(int k,int x) {//单点查询前驱 
		if(!k) return;
		if(v[k]<x) ans=k,querypre(r[k],x);
		else querypre(l[k],x);
	}
	void querysub(int k,int x) {//单点查询后继
		if(!k) return;
		if(v[k]>x) ans=k,querysub(l[k],x);
		else querysub(r[k],x);
	}
};
非旋转
struct FHQ_Treap{
	int l[2000005],r[2000005],sz[2000005],v[2000005],rnk[2000005],rt,tot;
	void pushup(int k) {sz[k]=sz[l[k]]+sz[r[k]]+1;}
	void split(int k,int val,int &x,int &y) {
		if(!k) {x=y=0;return;}
		if(v[k]<=val) x=k,split(r[k],val,r[k],y),pushup(k);
		else y=k,split(l[k],val,x,l[k]),pushup(k);
	}
	int merge(int x,int y) {
		if(!x||!y) return x+y;
		if(rnk[x]<rnk[y]) {r[x]=merge(r[x],y);pushup(x);return x;}
		else {l[y]=merge(x,l[y]);pushup(y);return y;}
	}
	void ins(int val) {//插入值val
		int a,b;split(rt,val,a,b);
		sz[++tot]=1,v[tot]=val,rnk[tot]=rand();
		rt=merge(merge(a,tot),b);
	}
	void del(int val) {//删除值为val的点
		int a,b,c;split(rt,val,a,c),split(a,val-1,a,b);
		b=merge(l[b],r[b]),rt=merge(merge(a,b),c);
	}
	int get_rank(int val) {//找值val的排名
		int a,b,res;split(rt,val-1,a,b);
		res=sz[a]+1,rt=merge(a,b);return res;
	}
	int get_num(int x,int k) {//在x子树内找排名为k的点
		if(sz[l[x]]+1==k) return v[x];
		else if(k<=sz[l[x]]) return get_num(l[x],k);
		else return get_num(r[x],k-sz[l[x]]-1);
	}
	int get_pre(int val) {//找值val的前驱点
		int a,b,res;split(rt,val-1,a,b);
		res=get_num(a,sz[a]),rt=merge(a,b);return res;
	}
	int get_sub(int val) {//找值val的后继点
		int a,b,res;split(rt,val,a,b);
		res=get_num(b,1),rt=merge(a,b);return res;
	}
};

9.堆

手打堆
struct Heap {//小根堆 
	int a[];
	void adjust(int p) {//调整 
		int lf=INT_MAX,rt=INT_MAX,minn;
		if(p*2<=n) lf=a[p*2];
		if(p*2+1<=n) rt=a[p*2+1];
		minn=min(a[p],min(lf,rt));
		if(minn==lf) {
			swap(a[p],a[p*2]);adjust(p*2);
			return;
		}
		if(minn==rt) {
			swap(a[p],a[p*2+1]);adjust(p*2+1);
			return;
		}
	} 
};
对顶堆
int sz=0;
priority_queue<int,vector<int>,greater<int> > pq1;//大根堆 
priority_queue<int> pq2;//小根堆
void adjust() {
	while(pq1.size()>pq2.size()+1)
		pq2.push(pq1.top()),pq1.pop();
	while(pq2.size()>pq1.size())
		pq1.push(pq2.top()),pq2.pop();
}
void add(int x) {
	if(!pq1.size()||x>=pq1.top())
		pq1.push(x);
	else
		pq2.push(x);
	adjust();
	sz++;
}
int query() {
	if(sz%2==0)
		return (pq1.top()+pq2.top())/2;
	return pq1.top();
}

10.并查集

int f[];
void init(int n) {for(int i=1;i<=n;i++) f[i]=i;}
int find(int x) {return (x==f[x]?x:f[x]=find(f[x]));}
void merge(int x,int y) {f[find(x)]=find(y);}

11.Trie树

int t[][],a[],cnt;
int f(char c) {}
void insert(string s) {
	int p=0,l=s.length();
	for(int i=0;i<l;++i) {
		int r=f(s[i]);
		if(!t[p][r])
			t[p][r]=++cnt;
		p=t[p][r];
	}
	++a[p];
}

12.左偏树

struct Node {int ls,rs,key,dis,fa;};
struct Leftist_Tree {
	Node p[];
	int build(int a[],int n) {
		queue<int> q;p[0].dis=-1;
		for(int i=1;i<=n;i++) q.push(i),p[++cnt]={0,0,a[i],0,i};
		while(q.size()>1) {
			int x=q.front();q.pop();
			int y=q.front();q.pop();
			q.push(merge(x,y));
		}
		return q.front();
	}
	int find(int x) {return (x==p[x].fa?x:p[x].fa=find(p[x].fa));}
	int merge(int a,int b) {
		if(!a||!b) return a+b;
		if(p[a].key>p[b].key) swap(a,b);
		p[a].rs=merge(p[a].rs,b);
		if(p[p[a].ls].dis<p[p[a].rs].dis) swap(p[a].ls,p[a].rs);
		p[p[a].ls].fa=p[p[a].rs].fa=p[x].fa=x,p[a].dis=p[p[a].rs].dis+1;
		return a;
	}
	int del(int x) {
		int ls=p[x].ls,rs=p[x].rs;
		p[ls].fa=ls,p[rs].fa=rs,p[x].ls=p[x].rs=p[x].dis=0;
		return merge(merge(ls,rs),find(x));
	}
};

13.分块

int cnt,sz,b[],bel[],bl[],br[];
void build(int n) {
	sz=sqrt(n),cnt=n/sz+(bool)(n%sz);
	for(int i=1;i<=n;i++)
		bel[i]=(i-1)/sz+1;
	for(int i=1;i<=cnt;i++)
		bl[i]=(i-1)*sz+1,br[i]=i*sz;
	br[cnt]=n;
}

14.Splay

struct Splay {
	int l[],r[],f[],v[],sz[],w[],rt,tot;
	void push_up(int now) {sz[now]=sz[l[now]]+sz[r[now]]+w[now];}
	void lrotate(int now) {
	    int fa=f[now];f[now]=f[fa];
	    if(l[f[fa]]==fa) l[f[fa]]=now;
	    if(r[f[fa]]==fa) r[f[fa]]=now;
	    f[fa]=now,r[fa]=l[now],f[l[now]]=fa,l[now]=fa,push_up(fa);
	}
	void rrotate(int now) {
	    int fa=f[now];f[now]=f[fa];
	    if(l[f[fa]]==fa) l[f[fa]]=now;
	    if(r[f[fa]]==fa) r[f[fa]]=now;
	    f[fa]=now,l[fa]=r[now],f[r[now]]=fa,r[now]=fa,push_up(fa);
	}
	void splay(int now,int FA=0) {
	    while(f[now]!=FA) {
	        int fa=f[now];
	        if(f[fa]==FA&&l[fa]==now) rrotate(now);
	        if(f[fa]==FA&&r[fa]==now) lrotate(now);
	        if(f[fa]!=FA&&l[f[fa]]==fa&&l[fa]==now) rrotate(fa),rrotate(now);
	        if(f[fa]!=FA&&l[f[fa]]==fa&&r[fa]==now) lrotate(now),rrotate(now);
	        if(f[fa]!=FA&&r[f[fa]]==fa&&l[fa]==now) rrotate(now),lrotate(now);
	        if(f[fa]!=FA&&r[f[fa]]==fa&&r[fa]==now) lrotate(fa),lrotate(now);
	    }
	    push_up(now),rt=(FA?rt:now);
	}
	void ins(int x) {//插入值x
	    for(int now=rt;;) {
	        if(now) sz[now]++;
	        if(v[now]==x) {w[now]++;splay(now);return;}
	        if(v[now]>x)
	            if(l[now]) now=l[now];
	            else {l[now]=++tot,sz[tot]=1,f[tot]=now,v[tot]=x,w[tot]=1,splay(tot);return;}
	        else
	       		if(r[now]) now=r[now];
	            else {r[now]=++tot,sz[tot]=1,f[tot]=now,v[tot]=x,w[tot]=1,splay(tot);return;}
	    }
	}
	int find(int x) {//找值x的对应点
	    int now=rt;
	    while(x!=v[now]) {
	    	if(v[now]<x&&r[now]) now=r[now];
	        else if(l[now]) now=l[now];
	        else break;
		}
	    splay(now);return now;
	}
	int get_lower(int x) {x=find(x);for(x=l[x];r[x];x=r[x]);return x;}//找值x的前驱点
	int get_upper(int x) {x=find(x);for(x=r[x];l[x];x=l[x]);return x;}//找值x的后继点
	void del(int x) {//删除值为x的点
	    int ll=get_lower(x),rr=get_upper(x);
	    splay(ll),splay(rr,ll);
	    if(w[l[rr]]>1) w[l[rr]]--,splay(l[rr]);
	    else l[rr]=0;
		push_up(rr),push_up(ll);
	}
	int get_rank(int x) {splay(x);return sz[l[x]]+1;}//找点x的排名
	int get_num(int k) {//找排名为k的点
	    for(int now=rt;;) {
	        if(sz[l[now]]+1>k&&l[now]) now=l[now];
	        else if(sz[l[now]]+w[now]<k&&r[now]) k-=sz[l[now]]+w[now],now=r[now];
	        else {splay(now);return now;}
	    }
	}
};

15.线性基

int d[];
void add(int x) {
	for(int i=31;i>=0;i--) {
		if(x&(1<<i)) {
			if(!d[i]) {d[i]=x;return;}
			x^=d[i];
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值