C++ 模板大全(持续更新)

C++模板大全(持续更新)

可通过点击右下角打开目录,快速跳转到你想要的章节。

怕以后找不到的话,可以收藏本文或关注我哦。

模板难度层层递进,跟着本文复习模板,效果会更好哦。

这里现在只有 \(50\) 个模板,以后将会持续更新。

【模板】排序

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,a[100005];
int main(){
	n=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
	}
	sort(a+1,a+n+1);
	for(ll i=1;i<=n;i++){
		write(a[i]);
		putchar(' ');
	}
	return 0;
}

【模板】快速幂

核心思想:

每一步都把指数分成两半,相应的底数做平方运算;最终求出的幂结果,实际上就是变化过程中所有「指数为奇数时」底数的乘积。

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll x,y,p;
ll ksm(ll x,ll y){
	ll res=1;
	while(y){
		if(y&1){//当指数为奇数时 
			res=res*x%p;
		}
		y>>=1;//指数缩为一半 
		x=x*x%p;
	}
	return res;
}
int main(){
	x=rd();
	y=rd();
	p=rd();
	write(x);
	putchar('^');
	write(y);
	printf(" mod ");
	write(p);
	putchar('=');
	write(ksm(x,y));
	return 0;
}

【模板】字符串哈希

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll p=13331,mod1=998244353,mod2=1e9+7;
ll n;
string s;
set<pair<ll,ll>> st;
ll gethash1(string x){
	ll hashx=0;
	for(ll i=0;i<x.size();i++){
		hashx=(hashx*p+x[i])%mod1;
	}
	return hashx;
}
ll gethash2(string x){
	ll hashx=0;
	for(ll i=0;i<x.size();i++){
		hashx=(hashx*p+x[i])%mod2;
	}
	return hashx;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n;
	for(ll i=1;i<=n;i++){
		cin>>s;
		st.insert({gethash1(s),gethash2(s)});
	}
	cout<<st.size();
	return 0;
}

【模板】线性筛素数

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,q,cnt,pri[100000005];
bool ispri[100000005];
void ols(){
	ispri[0]=ispri[1]=true;
	for(ll i=2;i<=n;i++){
		if(!ispri[i]){
			pri[++cnt]=i;
		}
		for(ll j=1;j<=cnt&&i*pri[j]<=n;j++){
			ispri[i*pri[j]]=true;
			if(i%pri[j]==0){
				break;
			}
		}
	}
}
int main(){
	n=rd();
	ols();
	q=rd();
	while(q--){
		write(pri[rd()]);
		putchar('\n');
	}
	return 0;
}

【模板】栈

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
ll t,n,x,a[1000005],top;
string s;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>t;
	while(t--){
		cin>>n;
		top=0;
		while(n--){
			cin>>s;
			if(s=="push"){
				cin>>x;
				a[++top]=x;
			}else if(s=="pop"){
				if(top==0){
					cout<<"Empty\n";
				}else{
					top--;
				}
			}else if(s=="query"){
				if(top==0){
					cout<<"Anguei!\n";
				}else{
					cout<<a[top]<<"\n";
				}
			}else{
				cout<<top<<"\n";
			}
		}
	}
	return 0;
}

【模板】队列

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,x;
queue<ll> q;
int main(){
	n=rd();
	while(n--){
		x=rd();
		if(x==1){
			x=rd();
			q.push(x);
		}else if(x==2){
			if(!q.empty()){
				q.pop();
			}else{
				printf("ERR_CANNOT_POP\n");
			}
		}else if(x==3){
			if(!q.empty()){
				write(q.front());
				putchar('\n');
			}else{
				printf("ERR_CANNOT_QUERY\n");
			}
		}else{
			write(q.size());
			putchar('\n');
		}
	}
	return 0;
}

【模板】双端队列 1

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxm=1e6+5;
ll n,cnt=-1;
string opt;
char ch;
map<ll,ll> mp;
vector<list<ll>> q;
int main(){
    n=rd();
    for(ll i=1;i<=n;i++){
        opt="";
        ch=gc();
        while(ch<'a'||ch>'z'){
            ch=gc();
        }
        while((ch>='a'&&ch<='z')||ch=='_'){
            opt+=ch;
            ch=gc();
        }
        ll a=rd();
        if(mp.count(a)==0){
            mp[a]=++cnt;
            q.push_back(list<ll>());
        }
        if(opt=="push_back"){
            ll x=rd();
            q[mp[a]].push_back(x);
        }else if(opt=="pop_back"){
            if(!q[mp[a]].empty()){
                q[mp[a]].pop_back();
            }
        }else if(opt=="push_front"){
            ll x=rd();
            q[mp[a]].push_front(x);
        }else if(opt=="pop_front"){
            if(!q[mp[a]].empty()){
                q[mp[a]].pop_front();
            }
        }else if(opt=="size"){
            write(q[mp[a]].size());
            putchar('\n');
        }else if(opt=="front"){
            if(!q[mp[a]].empty()){
                write(q[mp[a]].front());
                putchar('\n');
            }
        }else if(opt=="back"){
            if(!q[mp[a]].empty()){
                write(q[mp[a]].back());
                putchar('\n');
            }
        }
    }
	return 0;
}

【模板】数列离散化

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<3)+(x<<1)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e5+5;
ll t,n,a[maxn];
vector<ll> b;
int main(){
	t=rd();
	for(ll p=1;p<=t;p++){
		n=rd();
		b=vector<ll>();
		for(ll i=1;i<=n;i++){
			a[i]=rd();
			b.push_back(a[i]);
		}
		sort(b.begin(),b.end());
		b.erase(unique(b.begin(),b.end()),b.end());
		for(ll i=1;i<=n;i++){
			write(lower_bound(b.begin(),b.end(),a[i])-b.begin()+1);
			putchar(' ');
		}
		putchar('\n');
	}
	return 0;
}

【模板】快速读入

先打个广告:C++ 快读快写详解:读入整数与读入字符串(全网最详细)

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<3)+(x<<1)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e5+5;
ll n,x;
int main(){
	n=rd();
	for(ll i=1;i<=n;i++){
		x+=rd();
	}
	write(x);
	return 0;
}

【模板】单调队列 / 滑动窗口

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e6+5;
ll n,k,a[maxn];
deque<ll> q;
int main(){
	n=rd();
	k=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
	}
	for(ll i=1;i<=n;i++){
		while(!q.empty()&&a[q.back()]>a[i]){
			q.pop_back();
		}
		while(!q.empty()&&i-q.front()+1>k){
			q.pop_front();
		}
		q.push_back(i);
		if(i>=k){
			write(a[q.front()]);
			putchar(' ');
		}
	}
	putchar('\n');
	q=deque<ll>();
	for(ll i=1;i<=n;i++){
		while(!q.empty()&&a[q.back()]<a[i]){
			q.pop_back();
		}
		while(!q.empty()&&i-q.front()+1>k){
			q.pop_front();
		}
		q.push_back(i);
		if(i>=k){
			write(a[q.front()]);
			putchar(' ');
		}
	}
	return 0;
}

【模板】模意义下的乘法逆元

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,p,inv[3000005];
int main(){
	n=rd();
	p=rd();
	inv[1]=1;
	write(1);
	putchar('\n');
	for(ll i=2;i<=n;i++){
		inv[i]=(p-p/i)*inv[p%i]%p;
		write(inv[i]);
		putchar('\n');
	}
	return 0;
}

【模板】单调栈

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=3e6+5;
ll n,a[maxn],ans[maxn];
stack<ll> stk;
int main(){
	n=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
	}
	for(ll i=1;i<=n;i++){
		while(!stk.empty()&&a[stk.top()]<a[i]){
			ans[stk.top()]=i;
			stk.pop();
		}
		stk.push(i);
	}
	for(ll i=1;i<=n;i++){
		write(ans[i]);
		putchar(' ');
	}
	return 0;
}

【模板】最小生成树

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=5e3+5,maxm=2e5+5;
ll n,m,cnt,ans,f[maxn];
struct node{
	ll x,y,z;
}a[maxm];
bool cmp(node u,node v){
	return u.z<v.z;
}
ll find(ll x){
	return f[x]==x?x:f[x]=find(f[x]);
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=m;i++){
		a[i].x=rd();
		a[i].y=rd();
		a[i].z=rd();
	}
	for(ll i=1;i<=n;i++){
		f[i]=i;
	}
	sort(a+1,a+m+1,cmp);
	for(ll i=1;i<=m;i++){
		ll fx=find(a[i].x),fy=find(a[i].y);
		if(fx!=fy){
			f[fx]=fy;
			ans+=a[i].z;
			cnt++;
			if(cnt==n-1){
				write(ans);
				return 0;
			}
		}
	}
	printf("orz");
	return 0;
}

【模板】并查集

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
ll n,m,f[200005];
void init(){
	for(ll i=0;i<=n;i++){
		f[i]=i;
	}
}
ll find(ll x){
	return f[x]==x?x:f[x]=find(f[x]);
}
void merge(ll x,ll y){
	ll nx=find(x),ny=find(y);
	if(nx==ny){
		return;
	}
	f[nx]=ny;
}
int main(){
	n=rd();
    m=rd();
	init();
	for(ll i=1;i<=m;i++){
		ll z=rd(),x=rd(),y=rd();
		if(z==1){
			merge(x,y);
		}else{
			if(find(x)==find(y)){
				putchar('Y');
                putchar('\n');
			}else{
				putchar('N');
                putchar('\n');
			}
		}
	}
	return 0;
}

【模板】单源最短路径(SPFA)

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e4+5;
ll n,m,s,dis[maxn];
bool vis[maxn];
queue<ll> q;
struct node{
	ll to,val;
};
vector<node> e[maxn];
void spfa(){
	for(ll i=0;i<=n;i++){
		dis[i]=LLONG_MAX;
	}
	dis[s]=0;
	q.push(s);
	vis[s]=true;
	while(!q.empty()){
		ll x=q.front();
		q.pop();
		vis[x]=false;
		for(auto i:e[x]){
			ll y=i.to,v=i.val;
			if(dis[x]+v<dis[y]){
				dis[y]=dis[x]+v;
				if(!vis[y]){
					q.push(y);
					vis[y]=true;
				}
			}
		}
	}
}
int main(){
	n=rd();
	m=rd();
	s=rd();
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd(),w=rd();
		e[u].push_back({v,w});
	}
	spfa();
	for(ll i=1;i<=n;i++){
		if(dis[i]==LLONG_MAX){
			write((1<<31)-1);
			putchar(' ');
		}else{
			write(dis[i]);
			putchar(' ');
		}
	}
	return 0;
}

【模板】堆

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n;
priority_queue<ll,vector<ll>,greater<ll>> q;
int main(){
    n=rd();
    for(ll i=1;i<=n;i++){
        ll opt=rd();
        if(opt==1){
            ll x=rd();
            q.push(x);
        }else if(opt==2){
            write(q.top());
            putchar('\n');
        }else{
            q.pop();
        }
    }
	return 0;
}

【模板】最近公共祖先(LCA)

题目跳转

以下两种方法以速度快慢排序

树剖(964ms)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=5e5+5;
ll n,m,s,head[maxn<<1],cnt=1,f[maxn],son[maxn],top[maxn],siz[maxn],dep[maxn];
struct node{
	ll to,nxt;
}e[maxn<<1];
void add(ll u,ll v){
	e[++cnt].nxt=head[u];
	e[cnt].to=v;
	head[u]=cnt;
}
void dfs1(ll x,ll fa){
	f[x]=fa;
	siz[x]=1;
	dep[x]=dep[fa]+1;
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(y!=fa){
			dfs1(y,x);
			siz[x]+=siz[y];
			if(siz[y]>siz[son[x]]){
				son[x]=y;
			}
		}
	}
}
void dfs2(ll x,ll topf){
	top[x]=topf;
	if(son[x]){
		dfs2(son[x],topf);
	}
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(y!=f[x]&&y!=son[x]){
			dfs2(y,y);
		}
	}
}
ll ask(ll x,ll y){
	while(top[x]!=top[y]){
		if(dep[f[top[x]]]<dep[f[top[y]]]){
			swap(x,y);
		}
		x=f[top[x]];
	}
	if(dep[x]>dep[y]){
		swap(x,y);
	}
	return x;
}
int main(){
	n=rd();
	m=rd();
	s=rd();
	for(ll i=1;i<n;i++){
		ll u=rd(),v=rd();
		add(u,v);
		add(v,u);
	}
	cnt=0;
	dfs1(s,0);
	dfs2(s,s);
	for(ll i=1;i<=m;i++){
		ll a=rd(),b=rd();
		write(ask(a,b));
		putchar('\n');
	}
	return 0;
}

倍增(3.00s)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=5e5+5;
ll n,m,s,dep[maxn],f[maxn][21];
vector<ll> e[maxn];
void dfs(ll u,ll v){
    for(auto i:e[u]){
        if(i!=v){
            dep[i]=dep[u]+1;
            f[i][0]=u;
            dfs(i,u);
        }
    }
}
ll lca(ll u,ll v){
    if(dep[u]<dep[v]){
        swap(u,v);
    }
    for(ll i=20;i>=0;i--){
        if(((dep[u]-dep[v])>>i)&1){
            u=f[u][i];
        }
    }
    if(u==v){
        return u;
    }
    for(ll i=20;i>=0;i--){
        if(f[u][i]!=f[v][i]){
            u=f[u][i];
            v=f[v][i];
        }
    }
    return f[u][0];
}
int main(){
    n=rd();
    m=rd();
    s=rd();
    for(ll i=1;i<n;i++){
        ll u=rd(),v=rd();
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dep[s]=1;
    dfs(s,0);
    for(ll j=1;j<=20;j++){
        for(ll i=1;i<=n;i++){
            f[i][j]=f[f[i][j-1]][j-1];
        }
    }
    for(ll i=1;i<=m;i++){
        ll a=rd(),b=rd();
        cout<<lca(a,b)<<"\n";
    }
    return 0;
}

【模板】负环

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
const ll maxn=1e4+5;
ll t,n,m,dis[maxn],cnt[maxn];
bool vis[maxn];
queue<ll> q;
struct node{
	ll to,val;
};
vector<node> e[maxn];
bool spfa(){
	dis[1]=0;
	q.push(1);
	vis[1]=true;
	while(!q.empty()){
		ll x=q.front();
		q.pop();
		vis[x]=false;
		for(auto i:e[x]){
			ll y=i.to,v=i.val;
			if(dis[x]+v<dis[y]){
				dis[y]=dis[x]+v;
				if(!vis[y]){
                    cnt[y]++;
                    if(cnt[y]>=n){
                        return true;
                    }
					q.push(y);
					vis[y]=true;
				}
			}
		}
	}
    return false;
}
void solve(){
    n=rd();
	m=rd();
    for(ll i=0;i<=n;i++){
        vis[i]=false;
        e[i]=vector<node>();
        dis[i]=1e9;
        cnt[i]=0;
    }
    q=queue<ll>();
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd(),w=rd();
		e[u].push_back({v,w});
        if(w>=0){
            e[v].push_back({u,w});
        }
	}
	if(spfa()){
        printf("YES\n");
    }else{
        printf("NO\n");
    }
}
int main(){
    t=rd();
    for(ll i=1;i<=t;i++){
        solve();
    }
	return 0;
}

【模板】拓扑排序 / 家谱树

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e2+5;
ll n,ru[maxn];
queue<ll> q;
vector<ll> e[maxn],ans;
int main(){
	n=rd();
	for(ll i=1;i<=n;i++){
		ll x=rd();
		while(x){
			e[i].push_back(x);
			ru[x]++;
            x=rd();
		}
	}
	for(ll i=1;i<=n;i++){
		if(!ru[i]){
			q.push(i);
		}
	}
	while(!q.empty()){
		ll x=q.front();
		q.pop();
		ans.push_back(x);
		for(auto y:e[x]){
			ru[y]--;
			if(ru[y]==0){
				q.push(y);
			}
		}
	}
	for(auto i:ans){
		write(i);
		putchar(' ');
	}
	return 0;
}

【模板】Floyd

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,m;
int main(){
    n=rd();
    m=rd();
    vector<vector<ll>> dis(n+1,vector<ll>(n+1,1e9));
    for(ll i=1;i<=n;i++){
        dis[i][i]=0;
    }
    for(ll i=1;i<=m;i++){
        ll u=rd(),v=rd(),w=rd();
        dis[u][v]=min(dis[u][v],w);
        dis[v][u]=min(dis[v][u],w);
    }
    for(ll k=1;k<=n;k++){
        for(ll i=1;i<=n;i++){
            for(ll j=1;j<=n;j++){
                if(dis[i][k]!=1e9&&dis[k][j]!=1e9){
                    dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
                }
            }
        }
    }
    for(ll i=1;i<=n;i++){
        if(dis[i][i]<0){
            cout<<-1;
            return 0;
        }
    }
    for(ll i=1;i<=n;i++){
        for(ll j=1;j<=n;j++){
            write(dis[i][j]);
            putchar(' ');
        }
        putchar('\n');
    }
    return 0;
}

【模板】ST 表 & RMQ 问题

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,m,a[100005],f[100005][30];
void stmax(){
    for(ll i=1;i<=n;i++){
        f[i][0]=a[i];
    }
    ll k=__lg(n);
    for(ll j=1;j<=k;j++){
        for(ll i=1;i+(1<<j)-1<=n;i++){
            f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
}
ll fmax(ll l,ll r){
    ll k=__lg(r-l+1);
    return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main(){
    n=rd();
    m=rd();
    for(ll i=1;i<=n;i++){
        a[i]=rd();
    }
    stmax();
    while(m--){
        ll l=rd(),r=rd();
        write(fmax(l,r));
        putchar('\n');
    }
    return 0;
}

【模板】双向链表

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,m,x,y,pos,l[500005],r[500005];
bool del[500005];
int main(){
	n=rd();
	m=rd();
	r[0]=1;
	for(ll i=1;i<=n;i++){
		l[i]=i-1;
		r[i]=i+1;
	}
	r[n]=0;
	while(m--){
		x=rd();
		if(x==1){
			x=rd();
			y=rd();
			if(x!=y&&!del[x]&&!del[y]){
				r[l[x]]=r[x];
				l[r[x]]=l[x];
				l[x]=l[y];
				r[x]=y;
				r[l[y]]=x;
				l[y]=x;
			}
		}else if(x==2){
			x=rd();
			y=rd();
			if(x!=y&&!del[x]&&!del[y]){
				r[l[x]]=r[x];
				l[r[x]]=l[x];
				l[x]=y;
				r[x]=r[y];
				l[r[y]]=x;
				r[y]=x;
			}
		}else{
			x=rd();
			if(!del[x]){
				r[l[x]]=r[x];
				l[r[x]]=l[x];
				del[x]=true;
			}
		}
	}
	pos=r[0];
	if(pos==0){
		printf("Empty!");
	}else{
		while(pos!=0){
			write(pos);
			putchar(' ');
			pos=r[pos];
		}
	}
	return 0;
}

【模板】单源最短路径(dijkstra)

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
typedef pair<ll,ll> pll;
const ll maxn=1e5+5;
ll n,m,s,dis[maxn];
bool vis[maxn];
struct node{
	ll to,val;
};
vector<node> e[maxn];
int main(){
	n=rd();
	m=rd();
	s=rd();
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd(),w=rd();
		e[u].push_back({v,w});
	}
	for(ll i=0;i<=n;i++){
		dis[i]=LLONG_MAX;
	}
	priority_queue<pll,vector<pll>,greater<pll>> q;
	dis[s]=0;
	q.push({0,s});
	while(!q.empty()){
		ll x=q.top().second;
		q.pop();
		if(!vis[x]){
			vis[x]=true;
			for(auto y:e[x]){
				ll v=y.to,w=y.val;
				if(dis[x]+w<dis[v]){
					dis[v]=dis[x]+w;
					q.push({dis[v],v});
				}
			}
		}
	}
	for(ll i=1;i<=n;i++){
		write(dis[i]);
		putchar(' ');
	}
	return 0;
}

【模板】字典树 / Trie

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,Q,cnt;
struct node{
	ll son[62],tot;
}trie[3000005];
queue<ll> q;
void init(){
	cnt=0;
	q=queue<ll>();
	memset(trie[0].son,0,sizeof(trie[0].son));
    trie[0].tot=0;
}
void inst(string x){
	ll p=0,len=x.size();
	for(ll i=0;i<len;i++){
		ll j;
		if(x[i]>='a'&&x[i]<='z'){
			j=x[i]-'a'+36;
		}else if(x[i]>='A'&&x[i]<='Z'){
			j=x[i]-'A'+10;
		}else{
			j=x[i]-'0';
		}
		if(!trie[p].son[j]){
			trie[p].son[j]=++cnt;
            memset(trie[cnt].son,0,sizeof(trie[cnt].son));
    		trie[cnt].tot=0;
		}
		p=trie[p].son[j];
		trie[p].tot++;
	}
}
ll query(string x){
	ll p=0,len=x.size();
	for(ll i=0;i<len;i++){
		ll j;
		if(x[i]>='a'&&x[i]<='z'){
			j=x[i]-'a'+36;
		}else if(x[i]>='A'&&x[i]<='Z'){
			j=x[i]-'A'+10;
		}else{
			j=x[i]-'0';
		}
		if(!trie[p].son[j]){
			return 0;
		}
		p=trie[p].son[j];
	}
	return trie[p].tot;
}
string s;
void solve(){
	cin>>n>>Q;
	init();
	for(ll i=1;i<=n;i++){
		cin>>s;
		inst(s);
	}
	for(ll i=1;i<=Q;i++){
		cin>>s;
		cout<<query(s)<<"\n";
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>t;
	while(t--){
		solve();
	}
	return 0;
}

【模板】哈希表

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll mod=3e6+17;
ll rd(){
	ll x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-')f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=getchar();
	}
	return x*f;
}
void write(ll x){
	if(x>9){
        write(x/10);
    }
	putchar(x%10+'0');
}
ll n,x,y,r,cnt,ans;
unordered_map<ll,ll> mp[mod];
int main(){
	n=rd();
	for(ll i=1;i<=n;i++){
		x=rd();
		y=rd();
		r=x%mod;
		ans+=i*mp[r][x];
		mp[r][x]=y;
	}
	write(ans);
	return 0;
}

【模板】Nim 游戏

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
ll t,n,x,ans;
int main(){
    t=rd();
    for(ll j=1;j<=t;j++){
        ans=0;
        n=rd();
        for(ll i=1;i<=n;i++){
            x=rd();
            ans^=x;
        }
        if(ans==0){
            printf("No\n");
        }else{
            printf("Yes\n");
        }
    }
	return 0;
}

【模板】有理数取余

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll mod=19260817;
ll a,b;
char ch;
ll ksm(ll n,ll k){
    ll res=1;
    while(k){
        if(k&1){
            res=res*n%mod;
        }
        n=n*n%mod;
        k>>=1;
    }
    return res;
}
int main(){
    ch=gc();
    while(ch<'0'||ch>'9'){
        ch=gc();
    }
    while(ch>='0'&&ch<='9'){
        a=(((a<<1)+(a<<3))%mod+(ch-'0'))%mod;
        ch=gc();
    }
    while(ch<'0'||ch>'9'){
        ch=gc();
    }
    while(ch>='0'&&ch<='9'){
        b=(((b<<1)+(b<<3))%mod+(ch-'0'))%mod;
        ch=gc();
    }
    if(b==0){
        printf("Angry!");
    }else{
        ll ans=a*ksm(b,mod-2)%mod;
        write(ans);
    }
    return 0;
}

【模板】树状数组 1

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,m,x,y,c[500005];
ll lowbit(ll x){
	return x&-x;
}
void add(ll p,ll k){
	while(p<=n){
		c[p]+=k;
		p+=lowbit(p);
	}
}
ll query(ll p){
	ll res=0;
	while(p>0){
		res+=c[p];
		p-=lowbit(p);
	}
	return res;
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=n;i++){
		add(i,rd());
	}
	for(ll i=1;i<=m;i++){
		x=rd();
		if(x==1){
			x=rd();
			y=rd();
			add(x,y);
		}else{
			x=rd();
			y=rd();
			write(query(y)-query(x-1));
			putchar('\n');
		}
	}
	return 0;
}

【模板】树状数组 2

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
			f=-1;
		}
		ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=5e5+5;
ll n,m,a[maxn],c[maxn];
ll lowbit(ll x){
	return x&-x;
}
void add(ll p,ll k){
	while(p<=n){
		c[p]+=k;
		p+=lowbit(p);
	}
}
ll query(ll p){
	ll res=0;
	while(p>0){
		res+=c[p];
		p-=lowbit(p);
	}
	return res;
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
		add(i,a[i]-a[i-1]);
	}
	for(ll i=1;i<=m;i++){
		ll opt=rd(),x=rd(),y,k;
		if(opt==1){
			y=rd();
			k=rd();
			add(x,k);
			add(y+1,-k);
		}else{
			write(query(x));
			putchar('\n');
		}
	}
	return 0;
}

【模板】线段树 1

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
#define ls (p<<1)
#define rs (ls+1)
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e5+5;
ll n,m,a[maxn];
struct node{
	ll l,r,sum,tag;
}d[maxn<<2];
void pushup(ll p){
	d[p].sum=d[ls].sum+d[rs].sum;
}
void pushdown(ll p){
    d[ls].sum+=d[p].tag*(d[ls].r-d[ls].l+1);
    d[rs].sum+=d[p].tag*(d[rs].r-d[rs].l+1);
    d[ls].tag+=d[p].tag;
    d[rs].tag+=d[p].tag;
    d[p].tag=0;
}
void build(ll p,ll x,ll y){
	d[p].l=x;
	d[p].r=y;
	if(x==y){
		d[p].sum=a[x];
		return;
	}
	ll mid=(x+y)>>1;
	build(ls,x,mid);
	build(rs,mid+1,y);
	pushup(p);
}
void add(ll p,ll x,ll y,ll k){
    if(d[p].l>=x&&d[p].r<=y){
        d[p].sum+=k*(d[p].r-d[p].l+1);
        d[p].tag+=k;
        return;
    }
    pushdown(p);
    ll mid=(d[p].l+d[p].r)>>1;
    if(mid>=x){
        add(ls,x,y,k);
    }
    if(mid<y){
        add(rs,x,y,k);
    }
    pushup(p);
}
ll query(ll p,ll x,ll y){
    if(d[p].l>=x&&d[p].r<=y){
        return d[p].sum;
    }
    pushdown(p);
    ll mid=(d[p].l+d[p].r)>>1,ans=0;
    if(mid>=x){
        ans+=query(ls,x,y);
    }
    if(mid<y){
        ans+=query(rs,x,y);
    }
    return ans;
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
	}
	build(1,1,n);
	for(ll i=1;i<=m;i++){
        ll opt,x,y,k;
        opt=rd();
        x=rd();
        y=rd();
        if(opt==1){
            k=rd();
            add(1,x,y,k);
        }else{
            cout<<query(1,x,y)<<"\n";
        }
    }
	return 0;
}

【模板】线段树 2

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
#define ls (p<<1)
#define rs (ls+1)
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e5+5;
ll n,q,mod,a[maxn];
struct node{
	ll l,r,sum,tag1,tag2;
}d[maxn<<2];
void pushup(ll p){
	d[p].sum=(d[ls].sum+d[(p<<1)+1].sum)%mod;
}
void pushdown(ll p){
	d[ls].sum=(d[ls].sum*d[p].tag2+d[p].tag1*(d[ls].r-d[ls].l+1))%mod;
	d[rs].sum=(d[rs].sum*d[p].tag2+d[p].tag1*(d[rs].r-d[rs].l+1))%mod;
	d[ls].tag1=(d[ls].tag1*d[p].tag2+d[p].tag1)%mod;
	d[rs].tag1=(d[rs].tag1*d[p].tag2+d[p].tag1)%mod;
	d[ls].tag2=d[ls].tag2*d[p].tag2%mod;
	d[rs].tag2=d[rs].tag2*d[p].tag2%mod;
	d[p].tag1=0;
	d[p].tag2=1;
}
void build(ll p,ll x,ll y){
	d[p].l=x;
	d[p].r=y;
	d[p].tag2=1;
	if(x==y){
		d[p].sum=a[x];
		return;
	}
	ll mid=(x+y)>>1;
	build(ls,x,mid);
	build(rs,mid+1,y);
	pushup(p);
}
void mul(ll p,ll x,ll y,ll k){
	if(d[p].l>=x&&d[p].r<=y){
		d[p].sum=d[p].sum*k%mod;
		d[p].tag1=d[p].tag1*k%mod;
		d[p].tag2=d[p].tag2*k%mod;
		return;
	}
	pushdown(p);
	ll mid=(d[p].l+d[p].r)>>1;
	if(mid>=x){
		mul(ls,x,y,k);
	}
	if(mid<y){
		mul(rs,x,y,k);
	}
	pushup(p);
}
void add(ll p,ll x,ll y,ll k){
	if(d[p].l>=x&&d[p].r<=y){
		d[p].sum=(d[p].sum+k*(d[p].r-d[p].l+1))%mod;
		d[p].tag1=(d[p].tag1+k)%mod;
		return;
	}
	pushdown(p);
	ll mid=(d[p].l+d[p].r)>>1;
	if(mid>=x){
		add(ls,x,y,k);
	}
	if(mid<y){
		add(rs,x,y,k);
	}
	pushup(p);
}
ll query(ll p,ll x,ll y){
	if(d[p].l>=x&&d[p].r<=y){
		return d[p].sum;
	}
	pushdown(p);
	ll mid=(d[p].l+d[p].r)>>1,ans=0;
	if(mid>=x){
		ans=(ans+query(ls,x,y))%mod;
	}
	if(mid<y){
		ans=(ans+query(rs,x,y))%mod;
	}
	return ans;
}
int main(){
	n=rd();
	q=rd();
	mod=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
	}
	build(1,1,n);
	for(ll i=1;i<=q;i++){
		ll opt,x,y,k;
		opt=rd();
		x=rd();
		y=rd();
		if(opt==1){
			k=rd();
			mul(1,x,y,k);
		}else if(opt==2){
			k=rd();
			add(1,x,y,k);
		}else{
			write(query(1,x,y));
			putchar('\n');
		}
	}
	return 0;
}

【模板】KMP

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+5;
char s1[maxn],s2[maxn];
ll n1,n2,nxt[maxn];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>(s1+1)>>(s2+1);
	n1=strlen(s1+1);
	n2=strlen(s2+1);
	for(ll i=2,j=0;i<=n2;i++){
		while(j&&s2[i]!=s2[j+1]){
			j=nxt[j];
		}
		if(s2[i]==s2[j+1]){
			j++;
		}
		nxt[i]=j;
	}
	for(ll i=1,j=0;i<=n1;i++){
		while(j&&s1[i]!=s2[j+1]){
			j=nxt[j];
		}
		if(s1[i]==s2[j+1]){
			j++;
		}
		if(j==n2){
			cout<<i-j+1<<"\n";
			j=nxt[j];
		}
	}
	for(ll i=1;i<=n2;i++){
		cout<<nxt[i]<<" ";
	}
	return 0;
}

【模板】缩点 / 强连通分量

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e4+5;
ll n,m,cnt,scc,a[maxn],dfn[maxn],low[maxn],belong[maxn],val[maxn],ru[maxn],ans,dp[maxn];
vector<ll> e[maxn],g[maxn];
bool isin[maxn];
stack<ll> stk;
queue<ll> q;
void tarjan(ll x){
	dfn[x]=low[x]=++cnt;
	isin[x]=true;
	stk.push(x);
	for(auto y:e[x]){
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}else if(isin[y]){
			low[x]=min(low[x],dfn[y]);
		}
	}
	if(dfn[x]==low[x]){
		ll y;
		scc++;
		do{
			y=stk.top();
			stk.pop();
			isin[y]=false;
			belong[y]=scc;
			val[scc]+=a[y];
		}while(y!=x);
	}
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
	}
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd();
		e[u].push_back(v);
	}
	for(ll i=1;i<=n;i++){
		if(!dfn[i]){
			tarjan(i);
		}
	}
	for(ll x=1;x<=n;x++){
		for(auto y:e[x]){
			if(belong[x]!=belong[y]){
				g[belong[x]].push_back(belong[y]);
				ru[belong[y]]++;
			}
		}
	}
	for(ll i=1;i<=scc;i++){
		if(ru[i]==0){
			q.push(i);
			dp[i]=val[i];
		}
	}
	while(!q.empty()){
		ll x=q.front();
		q.pop();
		for(auto y:g[x]){
			dp[y]=max(dp[y],dp[x]+val[y]);
			ru[y]--;
			if(ru[y]==0){
				q.push(y);
			}
		}
	}
	for(ll i=1;i<=scc;i++){
		ans=max(ans,dp[i]);
	}
	write(ans);
	return 0;
}

【模板】割点

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=2e4+5;
ll n,m,cnt,ans,rt,dfn[maxn],low[maxn];
vector<ll> e[maxn];
bool cut[maxn];
void tarjan(ll x){
	dfn[x]=low[x]=++cnt;
	ll flag=0;
	for(auto y:e[x]){
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if(dfn[x]<=low[y]){
				flag++;
				if((flag>1||x!=rt)&&!cut[x]){
					ans++;
					cut[x]=true;
				}
			}
		}else{
			low[x]=min(low[x],dfn[y]);
		}
	}
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd();
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for(ll i=1;i<=n;i++){
		if(!dfn[i]){
			rt=i;
			tarjan(i);
		}
	}
	write(ans);
	putchar('\n');
	for(ll i=1;i<=n;i++){
		if(cut[i]){
			write(i);
			putchar(' ');
		}
	}
	return 0;
}

【模板】矩阵快速幂

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e2+5,mod=1e9+7;
ll n,k,a[maxn][maxn],c[maxn][maxn],ans[maxn][maxn];
void mul1(){
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			c[i][j]=0;
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			for(ll k=1;k<=n;k++){
				c[i][j]=(c[i][j]+ans[i][k]*a[k][j])%mod;
			}
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			ans[i][j]=c[i][j];
		}
	}
}
void mul2(){
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			c[i][j]=0;
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			for(ll k=1;k<=n;k++){
				c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
			}
		}
	}
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			a[i][j]=c[i][j];
		}
	}
}
void ksm(ll b){
	while(b){
		if(b&1){
			mul1();
		}
		mul2();
		b>>=1;
	}
}
int main(){
	n=rd();
	k=rd();
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			a[i][j]=rd();
		}
		ans[i][i]=1;
	}
	ksm(k);
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			write(ans[i][j]);
			putchar(' ');
		}
		putchar('\n');
	}
	return 0;
}

【模板】欧拉路径

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e5+5;
ll n,m,rt=1,ru[maxn],chu[maxn],cnt[2],st[maxn];
bool flag;
struct node{
	ll v;
	bool vis;
};
vector<node> e[maxn];
stack<ll> stk;
bool cmp(node x,node y){
	return x.v<y.v;
}
void dfs(ll x){
	for(ll i=0;i<e[x].size();i=max(i+1,st[x])){
		if(!e[x][i].vis){
			e[x][i].vis=true;
			st[x]=i+1;
			dfs(e[x][i].v);
		}
	}
	stk.push(x);
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd();
		e[u].push_back({v,false});
		chu[u]++;
		ru[v]++;
	}
	for(ll i=1;i<=n;i++){
		if(ru[i]!=chu[i]){
			flag=true;
			if(ru[i]-chu[i]==1){
				cnt[0]++;
			}else if(chu[i]-ru[i]==1){
				cnt[1]++;
				rt=i;
			}else{
				printf("No");
				return 0;
			}
		}
	}
	if(flag&&!(cnt[0]==cnt[1]&&cnt[0]==1)){
		printf("No");
	}else{
		for(ll i=1;i<=n;i++){
			sort(e[i].begin(),e[i].end(),cmp);
		}
		dfs(rt);
		while(!stk.empty()){
			write(stk.top());
			putchar(' ');
			stk.pop();
		}
	}
	return 0;
}

【模板】点双连通分量

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn1=5e5+5,maxn2=2e6+5;
ll n,m,rt,cnt=1,num,tot,head[maxn1],dfn[maxn1],low[maxn1],fa[maxn1];
stack<ll> stk;
struct node{
	ll to,nxt;
}e[maxn2<<1];
void add(ll u,ll v){
	if(u!=v){
		e[++cnt].nxt=head[u];
		head[u]=cnt;
		e[cnt].to=v;
	}
}
vector<ll> scc[maxn1];
void dfs(ll x){
	low[x]=dfn[x]=++tot;
	stk.push(x);
	if(x==rt&&head[x]==0){
		scc[++num].push_back(x);
		return;
	}
	for(ll i=head[x];i;i=e[i].nxt){
		if(i!=(fa[x]^1)){
			ll y=e[i].to;
			if(!dfn[y]){
				fa[y]=i;
				dfs(y);
				low[x]=min(low[x],low[y]);
				if(dfn[x]<=low[y]){
					num++;
					ll j;
					do{
						j=stk.top();
						stk.pop();
						scc[num].push_back(j);
					}while(j!=y);
					scc[num].push_back(x);
				}
			}else{
				low[x]=min(low[x],dfn[y]);
			}
		}
	}
}
int main(){
	n=rd();
    m=rd();
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd();
		add(u,v);
		add(v,u);
	}
	for(ll i=1;i<=n;i++){
		if(!dfn[i]){
			rt=i;
			dfs(i);
		}
	}
	write(num);
    putchar('\n');
	for(ll i=1;i<=num;i++){
		write(scc[i].size());
        putchar(' ');
		for(auto j:scc[i]){
			write(j);
            putchar(' ');
		}
		putchar('\n');
	}
	return 0;
}

【模板】边双连通分量

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn1=5e5+5,maxn2=2e6+5;
bool cut[maxn2<<1];
ll n,m,cnt=1,tot,k,head[maxn1],fa[maxn1],dfn[maxn1],low[maxn1],scc[maxn1];
struct node{
	ll to,nxt;
}e[maxn2<<1];
vector<ll> ans[maxn1];
void add(ll u,ll v){
	e[++cnt].nxt=head[u];
	head[u]=cnt;
	e[cnt].to=v;
}
void dfs1(ll x){
	dfn[x]=low[x]=++tot;
	for(ll i=head[x];i;i=e[i].nxt){
		if(i!=(fa[x]^1)){
			ll y=e[i].to;
			if(!dfn[y]){
				fa[y]=i;
				dfs1(y);
				low[x]=min(low[x],low[y]);
				if(dfn[x]<low[y]){
					cut[fa[y]]=cut[fa[y]^1]=true;
				}
			}else{
				low[x]=min(low[x],dfn[y]);
			}
		}
	}
}
void dfs2(ll x){
	scc[x]=k;
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(!scc[y]&&!cut[i]){
			dfs2(y);
		}
	}
}
int main(){
	n=rd();
    m=rd();
	for(ll i=1;i<=m;i++){
		ll u=rd(),v=rd();
		add(u,v);
		add(v,u);
	}
	for(ll i=1;i<=n;i++){
		if(!dfn[i]){
			dfs1(i);
		}
	}
	for(ll i=1;i<=n;i++){
		if(!scc[i]){
			k++;
			dfs2(i);
		}
	}
	write(k);
    putchar('\n');
	for(ll i=1;i<=n;i++){
		ans[scc[i]].push_back(i);
	}
	for(ll i=1;i<=k;i++){
		write(ans[i].size());
        putchar(' ');
		for(auto j:ans[i]){
			write(j);
            putchar(' ');
		}
		putchar('\n');
	}
	return 0;
}

【模板】动态开点线段树(线段树1.5)

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=5e6+5;
ll n,m,rt,cnt;
struct node{
	ll ls,rs,sum,tag;
}d[maxn];
void pushup(ll p){
	d[p].sum=0;
	if(d[p].ls){
		d[p].sum+=d[d[p].ls].sum;
	}
	if(d[p].rs){
		d[p].sum+=d[d[p].rs].sum;
	}
}
void pushdown(ll p,ll l,ll r){
	ll mid=(l+r)>>1;
	if(d[p].tag){
		if(!d[p].ls){
			d[p].ls=++cnt;
		}
		if(!d[p].rs){
			d[p].rs=++cnt;
		}
		d[d[p].ls].sum+=d[p].tag*(mid-l+1);
		d[d[p].rs].sum+=d[p].tag*(r-mid);
		d[d[p].ls].tag+=d[p].tag;
		d[d[p].rs].tag+=d[p].tag;
		d[p].tag=0;
	}
}
void add(ll &p,ll l,ll r,ll x,ll y,ll k){
	if(!p){
		p=++cnt;
	}
	if(l>=x&&r<=y){
		d[p].sum+=k*(r-l+1);
		d[p].tag+=k;
		return;
	}
	pushdown(p,l,r);
	ll mid=(l+r)>>1;
	if(mid>=x){
		add(d[p].ls,l,mid,x,y,k);
	}
	if(mid<y){
		add(d[p].rs,mid+1,r,x,y,k);
	}
	pushup(p);
}
ll query(ll p,ll l,ll r,ll x,ll y){
	if(!p){
		return 0;
	}
	if(l>=x&&r<=y){
		return d[p].sum;
	}
	pushdown(p,l,r);
	ll mid=(l+r)>>1,ans=0;
	if(mid>=x){
		ans+=query(d[p].ls,l,mid,x,y);
	}
	if(mid<y){
		ans+=query(d[p].rs,mid+1,r,x,y);
	}
	return ans;
}
int main(){
	n=rd();
	m=rd();
	for(ll i=1;i<=m;i++){
		ll x,y,z;
		x=rd();
		if(x==1){
			x=rd();
			y=rd();
			z=rd();
			add(rt,1,n,x,y,z);
		}else{
			x=rd();
			y=rd();
			write(query(rt,1,n,x,y)+(((x+y)*(y-x+1))>>1));
			putchar('\n');
		}
	}
	return 0;
}

【模板】Manacher

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1.1e7+5;
string s,tmp;
ll n,r,mid,p[maxn<<1],ans;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>tmp;
	s="@#";
	for(ll i=0;i<tmp.size();i++){
		s+=tmp[i];
		s+='#';
	}
	s+='$';
	n=s.size();
	for(ll i=0;i<n;i++){
		if(i<r){
			p[i]=min(p[(mid<<1)-i],r-i);
		}else{
			p[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]-1);
	}
	cout<<ans;
	return 0;
}

【模板】扫描线 & 矩形面积并

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define ls (p<<1)
#define rs ((p<<1)|1)
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e5+5;
ll n,y[maxn<<1],ans;
struct node{
	ll y1,y2,x,mark;
}line[maxn<<1];
bool cmp(node u,node v){
	return u.x<v.x;
}
struct tree{
	ll l,r,sum,tag;
}d[maxn<<3];
void pushup(ll p){
	if(!d[p].tag){
		if(d[p].l==d[p].r){
			d[p].sum=0;
		}else{
			d[p].sum=d[ls].sum+d[rs].sum;
		}
	}
}
void build(ll p,ll x,ll yy){
	d[p].l=x;
	d[p].r=yy;
	if(x==yy){
		return;
	}
	ll mid=(x+yy)>>1;
	build(ls,x,mid);
	build(rs,mid+1,yy);
}
void change(ll p,ll x,ll yy,ll k){
    if(d[p].l>=x&&d[p].r<=yy){
        d[p].tag+=k;
        if(d[p].tag){
        	d[p].sum=y[d[p].r+1]-y[d[p].l];
		}else{
			d[p].sum=0;
		}
		pushup(p);
        return;
    }
    ll mid=(d[p].l+d[p].r)>>1;
    if(mid>=x){
        change(ls,x,yy,k);
    }
	if(mid<yy){
        change(rs,x,yy,k);
    }
    pushup(p);
}
int main(){
	n=rd();
	for(ll i=1;i<=n;i++){
		ll x1=rd(),y1=rd(),x2=rd(),y2=rd();
		y[(i<<1)-1]=y1;
		y[i<<1]=y2;
		line[(i<<1)-1]={y1,y2,x1,1};
		line[i<<1]={y1,y2,x2,-1};
	}
	n<<=1;
	sort(y+1,y+n+1);
	sort(line+1,line+n+1,cmp);
	ll m=unique(y+1,y+n+1)-y-2;
	build(1,1,m);
	for(ll i=1;i<n;i++){
		ll y1=lower_bound(y+1,y+m+2,line[i].y1)-y;
		ll y2=lower_bound(y+1,y+m+2,line[i].y2)-y-1;
		change(1,y1,y2,line[i].mark);
		ans+=d[1].sum*(line[i+1].x-line[i].x);
	}
	write(ans);
	return 0;
}

【模板】二元一次不定方程 (exgcd)

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1,y=0;
        return a;
    }
    ll gcd=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return gcd;
}
ll cd(ll a,ll b){
    ll q=a/b,r=a%b;
    if(r>0){
        q++;
    }
    return q;
}
ll fd(ll a,ll b){
    ll q=a/b,r=a%b;
    if(r<0){
        q--;
    }
    return q;
}
void solve(){
    ll a,b,c,x0,y0;
    a=rd();
    b=rd();
    c=rd();
    ll gcd=exgcd(a,b,x0,y0);
    if(c%gcd!=0){
        cout<<-1<<endl;
        return;
    }
    ll mul=c/gcd,k=b/gcd,l=a/gcd;
    x0*=mul,y0*=mul;
    ll tmin=cd(1-x0,k),tmax=fd(y0-1,l);
    ll xmin=x0+k*tmin,ymin=y0-l*tmax;
    if(tmin<=tmax){
        ll cnt=tmax-tmin+1,xmax=x0+k*tmax,ymax=y0-l*tmin;
        write(cnt);
        putchar(' ');
        write(xmin);
        putchar(' ');
        write(ymin);
        putchar(' ');
        write(xmax);
        putchar(' ');
        write(ymax);
        putchar('\n');
    }else{
        write(xmin);
        putchar(' ');
        write(ymin);
        putchar('\n');
    }
}
int main(){
    ll t;
    t=rd();
    for(ll i=1;i<=t;i++){
        solve();
    }
    return 0;
}

【模板】失配树

依旧打个广告:失配树模板题 题解

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+5;
ll n,m,p,q,nxt[maxn],dep[maxn],f[maxn][21];
char s[maxn];
vector<ll> e[maxn];
void dfs(ll x,ll fa){
	dep[x]=dep[fa]+1;
	f[x][0]=fa;
	for(ll i=1;i<=20;i++){
		f[x][i]=f[f[x][i-1]][i-1];
	}
	for(auto y:e[x]){
		dfs(y,x);
	}
}
ll lca(ll u,ll v){
	if(dep[u]<dep[v]){
		swap(u,v);
	}
	for(ll i=20;i>=0;i--){
		if(dep[f[u][i]]>=dep[v]){
			u=f[u][i];
		}
	}
	for(ll i=20;i>=0;i--){
		if(f[u][i]!=f[v][i]){
			u=f[u][i];
			v=f[v][i];
		}
	}
	return f[u][0];
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>(s+1)>>m;
	n=strlen(s+1);
	for(ll i=2,j=0;i<=n;i++){
		while(j&&s[i]!=s[j+1]){
			j=nxt[j];
		}
		if(s[i]==s[j+1]){
			j++;
		}
		nxt[i]=j;
	}
	for(ll i=1;i<=n;i++){
		e[nxt[i]+1].push_back(i+1);
	}
	dfs(1,0); 
	while(m--){
		cin>>p>>q;
		cout<<lca(p+1,q+1)-1<<"\n";
	}
	return 0;
}

【模板】最小表示法

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;
string s;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n>>s;
	ll i=0,j=1,k=0;
	while(i<n&&j<n&&k<n){
		if(s[(i+k)%n]==s[(j+k)%n]){
			k++;
		}else{
			if(s[(i+k)%n]>s[(j+k)%n]){
				i+=k+1;
			}else{
				j+=k+1;
			}
			if(i==j){
				j++;
			}
			k=0;
		}
	}
	for(ll p=min(i,j);p<n;p++){
		cout<<s[p];
	}
	for(ll p=0;p<min(i,j);p++){
		cout<<s[p];
	}
	return 0;
}

【模板】普通平衡树

题目跳转

以下三种方法以速度快慢排序

旋转treap(157ms)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
mt19937 gen(19620817);
ll n,cnt,rt;
struct node{
    ll l,r,size,val,data;
}t[100005];
void pushup(ll p){
    t[p].size=t[t[p].l].size+t[t[p].r].size+1;
}
void lxuan(ll &p){
    ll tmp=t[p].r;
    t[p].r=t[tmp].l;
    t[tmp].l=p;
    t[tmp].size=t[p].size;
    pushup(p);
    p=tmp;
}
void rxuan(ll &p){
    ll tmp=t[p].l;
    t[p].l=t[tmp].r;
    t[tmp].r=p;
    t[tmp].size=t[p].size;
    pushup(p);
    p=tmp;
}
void insert(ll &p,ll x){
    if(p==0){
        p=++cnt;
        t[p].size=1;
        t[p].data=x;
        t[p].val=gen()*gen()%19620817;
        return;
    }
    t[p].size++;
    if(x>=t[p].data){
        insert(t[p].r,x);
    }else{
        insert(t[p].l,x);
    }
    if(t[p].l!=0&&t[p].val>t[t[p].l].val){
        rxuan(p);
    }
    if(t[p].r!=0&&t[p].val>t[t[p].r].val){
        lxuan(p);
    }
    pushup(p);
}
void erase(ll &p,ll x){
    t[p].size--;
    if(t[p].data==x){
        if(t[p].l==0&&t[p].r==0){
            p=0;
            return;
        }
        if(t[p].l==0||t[p].r==0){
            p=t[p].l+t[p].r;
            return;
        }
        if(t[t[p].l].val<t[t[p].r].val){
            rxuan(p);
            erase(t[p].r,x);
            return;
        }else{
            lxuan(p);
            erase(t[p].l,x);
            return;
        }
    }
    if(t[p].data>=x){
        erase(t[p].l,x);
    }else{
        erase(t[p].r,x);
    }
    pushup(p);
}
ll Rank(ll p,ll x){
    if(p==0){
        return 0;
    }
    if(x>t[p].data){
        return t[t[p].l].size+1+Rank(t[p].r,x);
    }
    return Rank(t[p].l,x);
}
ll find(ll p,ll x){
    if(x==t[t[p].l].size+1){
        return t[p].data;
    }
    if(x>t[t[p].l].size+1){
        return find(t[p].r,x-t[t[p].l].size-1);
    }
    return find(t[p].l,x);
}
ll query_pre(ll p,ll x){
    if(p==0){
        return 0;
    }
    if(t[p].data>=x){
        return query_pre(t[p].l,x);
    }
    ll tmp=query_pre(t[p].r,x);
    if(tmp==0){
        return t[p].data;
    }
    return tmp;
}
ll query_suf(ll p,ll x){
    if(p==0){
        return 0;
    }
    if(t[p].data<=x){
        return query_suf(t[p].r,x);
    }
    ll tmp=query_suf(t[p].l,x);
    if(tmp==0){
        return t[p].data;
    }
    return tmp;
}
int main(){
    n=rd();
    while(n--){
        ll opt=rd(),x=rd();
        if(opt==1){
            insert(rt,x);
        }else if(opt==2){
            erase(rt,x);
        }else if(opt==3){
            write(Rank(rt,x)+1);
            putchar('\n');
        }else if(opt==4){
            write(find(rt,x));
            putchar('\n');
        }else if(opt==5){
            write(query_pre(rt,x));
            putchar('\n');
        }else{
            write(query_suf(rt,x));
            putchar('\n');
        }
    }
    return 0;
}

pbds库(165ms)

cpp 复制代码
#include<bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
typedef pair<ll,ll> pll;
ll n,cnt;
int main(){
    n=rd();
    tree<pll,null_type,less<pll>,rb_tree_tag,tree_order_statistics_node_update> tr;
    while(n--){
        ll opt=rd(),x=rd();
        if(opt==1){
            tr.insert({x,++cnt});
        }else if(opt==2){
            auto it=tr.lower_bound({x,0});
            if(it!=tr.end()){
                tr.erase(it);
            }
        }else if(opt==3){
            write(tr.order_of_key({x,0})+1);
            putchar('\n');
        }else if(opt==4){
            auto it=tr.find_by_order(x-1);
            if(it!=tr.end()){
                write(it->first);
                putchar('\n');
            }
        }else if(opt==5){
            auto it=tr.lower_bound({x,0});
            it--;
            write(it->first);
            putchar('\n');
        }else{
            write(tr.lower_bound({x+1,0})->first);
            putchar('\n');
        }
    }
    return 0;
}

非旋treap(FHQ)(238ms)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
mt19937 gen(time(0));
ll n,rt,cnt;
struct node{
    ll l,r,size,val,data=gen();
    node(ll _l=0,ll _r=0,ll _size=0,ll _val=0,ll _data=gen()){
        l=_l,r=_r,size=_size,val=_val,data=_data;
    }
}t[100005];
void pushup(ll p){
    t[p].size=t[t[p].l].size+t[t[p].r].size+1;
}
ll newnode(ll p){
    t[++cnt]=node(0,0,1,p);
    return cnt;
}
void split(ll p,ll val,ll &x,ll &y){
    if(p==0){
        x=0;
        y=0;
        return;
    }
    if(t[p].val<=val){
        x=p;
        split(t[x].r,val,t[x].r,y);
        pushup(p);
    }else{
        y=p;
        split(t[p].l,val,x,t[p].l);
        pushup(p);
    }
}
ll merge(ll x,ll y){
    if(x==0||y==0){
        return x+y;
    }
    if(t[x].data<t[y].data){
        t[x].r=merge(t[x].r,y);
        pushup(x);
        return x;
    }else{
        t[y].l=merge(x,t[y].l);
        pushup(y);
        return y;
    }
}
void insert(ll p){
    ll rt1,rt2;
    split(rt,p,rt1,rt2);
    rt=merge(merge(rt1,newnode(p)),rt2);
}
void erase(ll p){
    ll rt1,rt2,rt3;
    split(rt,p,rt1,rt2);
    split(rt1,p-1,rt1,rt3);
    rt3=merge(t[rt3].l,t[rt3].r);
    rt=merge(merge(rt1,rt3),rt2);
}
ll kth(ll p){
    ll now=rt;
    while(1){
        if(p==t[t[now].l].size+1){
            break;
        }
        if(p<t[t[now].l].size+1){
            now=t[now].l;
        }else{
            p-=t[t[now].l].size+1;
            now=t[now].r;
        }
    }
    return now;
}
ll Rank(ll p){
    ll rt1,rt2,res=0;
    split(rt,p-1,rt1,rt2);
    res=t[rt1].size+1;
    rt=merge(rt1,rt2);
    return res;
}
int main(){
    n=rd();
    while(n--){
        ll opt=rd(),x=rd();
        if(opt==1){
            insert(x);
        }else if(opt==2){
            erase(x);
        }else if(opt==3){
            write(Rank(x));
            putchar('\n');
        }else if(opt==4){
            write(t[kth(x)].val);
            putchar('\n');
        }else if(opt==5){
            write(t[kth(Rank(x)-1)].val);
            putchar('\n');
        }else{
            write(t[kth(Rank(x+1))].val);
            putchar('\n');
        }
    }
    return 0;
}

【模板】普通平衡树(数据加强版)

题目跳转

以下三种方式按速度快慢排序

旋转treap(8.59s)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
mt19937 gen(19620817);
ll n,m,cnt,rt,ans,last;
struct node{
    ll l,r,size,val,data;
}t[1100005];
void pushup(ll p){
    t[p].size=t[t[p].l].size+t[t[p].r].size+1;
}
void lxuan(ll &p){
    ll tmp=t[p].r;
    t[p].r=t[tmp].l;
    t[tmp].l=p;
    t[tmp].size=t[p].size;
    pushup(p);
    p=tmp;
}
void rxuan(ll &p){
    ll tmp=t[p].l;
    t[p].l=t[tmp].r;
    t[tmp].r=p;
    t[tmp].size=t[p].size;
    pushup(p);
    p=tmp;
}
void Insert(ll &p,ll x){
    if(p==0){
        p=++cnt;
        t[p].size=1;
        t[p].data=x;
        t[p].val=gen()*gen()%19620817;
        return;
    }
    t[p].size++;
    if(x>=t[p].data){
        Insert(t[p].r,x);
    }else{
        Insert(t[p].l,x);
    }
    if(t[p].l!=0&&t[p].val>t[t[p].l].val){
        rxuan(p);
    }
    if(t[p].r!=0&&t[p].val>t[t[p].r].val){
        lxuan(p);
    }
    pushup(p);
}
void Erase(ll &p,ll x){
    t[p].size--;
    if(t[p].data==x){
        if(t[p].l==0&&t[p].r==0){
            p=0;
            return;
        }
        if(t[p].l==0||t[p].r==0){
            p=t[p].l+t[p].r;
            return;
        }
        if(t[t[p].l].val<t[t[p].r].val){
            rxuan(p);
            Erase(t[p].r,x);
            return;
        }else{
            lxuan(p);
            Erase(t[p].l,x);
            return;
        }
    }
    if(t[p].data>=x){
        Erase(t[p].l,x);
    }else{
        Erase(t[p].r,x);
    }
    pushup(p);
}
ll Rank(ll p,ll x){
    if(p==0){
        return 0;
    }
    if(x>t[p].data){
        return t[t[p].l].size+1+Rank(t[p].r,x);
    }
    return Rank(t[p].l,x);
}
ll find(ll p,ll x){
    if(x==t[t[p].l].size+1){
        return t[p].data;
    }
    if(x>t[t[p].l].size+1){
        return find(t[p].r,x-t[t[p].l].size-1);
    }
    return find(t[p].l,x);
}
ll query_pre(ll p,ll x){
    if(p==0){
        return 0;
    }
    if(t[p].data>=x){
        return query_pre(t[p].l,x);
    }
    ll tmp=query_pre(t[p].r,x);
    if(tmp==0){
        return t[p].data;
    }
    return tmp;
}
ll query_suf(ll p,ll x){
    if(p==0){
        return 0;
    }
    if(t[p].data<=x){
        return query_suf(t[p].r,x);
    }
    ll tmp=query_suf(t[p].l,x);
    if(tmp==0){
        return t[p].data;
    }
    return tmp;
}
int main(){
    n=rd();
    m=rd();
    for(ll i=1;i<=n;i++){
        Insert(rt,rd());
    }
    while(m--){
        ll opt=rd(),x=rd();
        x^=last;
        if(opt==1){
            Insert(rt,x);
        }else if(opt==2){
            Erase(rt,x);
        }else if(opt==3){
            last=(Rank(rt,x)+1);
        }else if(opt==4){
            last=find(rt,x);
        }else if(opt==5){
            last=query_pre(rt,x);
        }else{
            last=query_suf(rt,x);
        }
        if(opt>=3&&opt<=6){
            ans^=last;
        }
    }
    write(ans);
    return 0;
}

非旋treap(FHQ)(11.55s)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
ll n,m,rt,cnt,last,ans;
struct node{
    ll l,r,size,val,data;
    node(ll _l=0,ll _r=0,ll _size=0,ll _val=0,ll _data=rand()){
        l=_l,r=_r,size=_size,val=_val,data=_data;
    }
}t[1100005];
void pushup(ll p){
    t[p].size=t[t[p].l].size+t[t[p].r].size+1;
}
ll newnode(ll p){
    t[++cnt]=node(0,0,1,p);
    return cnt;
}
void split(ll p,ll val,ll &x,ll &y){
    if(!p){
        x=y=0;
        return;
    }
    if(t[p].val<=val){
        x=p;
        split(t[p].r,val,t[p].r,y);
    }else{
        y=p;
        split(t[p].l,val,x,t[p].l);
    }
    pushup(p);
}
ll merge(ll x,ll y){
    if(x==0||y==0){
        return x+y;
    }
    if(t[x].data<t[y].data){
        t[x].r=merge(t[x].r,y);
        pushup(x);
        return x;
    }else{
        t[y].l=merge(x,t[y].l);
        pushup(y);
        return y;
    }
}
void insert(ll p){
    ll rt1,rt2;
    split(rt,p,rt1,rt2);
    rt=merge(merge(rt1,newnode(p)),rt2);
}
void erase(ll p){
    ll rt1,rt2,rt3;
    split(rt,p,rt1,rt2);
    split(rt1,p-1,rt1,rt3);
    rt3=merge(t[rt3].l,t[rt3].r);
    rt=merge(merge(rt1,rt3),rt2);
}
ll kth(ll p){
    ll now=rt;
    while(p!=t[t[now].l].size+1){
        if(p<t[t[now].l].size+1){
            now=t[now].l;
        }else{
            p-=t[t[now].l].size+1;
            now=t[now].r;
        }
    }
    return now;
}
ll Rank(ll p){
    ll now=rt,res=0;
    while(now){
        if(p>t[now].val){
            res+=t[t[now].l].size+1;
            now=t[now].r;
        }else{
            now=t[now].l;
        }
    }
    return res+1;
}
int main(){
    n=rd();
    m=rd();
    for(ll i=1;i<=n;i++){
        ll x=rd();
        insert(x);
    }
    while(m--){
        ll opt=rd(),x=rd();
        x^=last;
        if(opt==1){
            insert(x);
        }else if(opt==2){
            erase(x);
        }else if(opt==3){
            last=Rank(x);
        }else if(opt==4){
            last=t[kth(x)].val;
        }else if(opt==5){
            last=t[kth(Rank(x)-1)].val;
        }else{
            last=t[kth(Rank(x+1))].val;
        }
        if(opt>=3&&opt<=6){
            ans^=last;
        }
    }
    write(ans);
    return 0;
}

pbds库(13.20s)

cpp 复制代码
#include<bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
typedef int ll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
typedef pair<ll,ll> pll;
ll n,m,cnt,last,ans;
int main(){
    n=rd();
    m=rd();
    tree<pll,null_type,less<pll>,rb_tree_tag,tree_order_statistics_node_update> tr;
    for(ll i=1;i<=n;i++){
        ll x=rd();
        tr.insert({x,++cnt});
    }
    while(m--){
        ll opt=rd(),x=rd();
        x^=last;
        if(opt==1){
            tr.insert({x,++cnt});
        }else if(opt==2){
            tr.erase(tr.lower_bound({x,0}));
        }else if(opt==3){
            last=tr.order_of_key({x,0})+1;
        }else if(opt==4){
            auto it=tr.find_by_order(x-1);
            last=it->first;
        }else if(opt==5){
            auto it=tr.lower_bound({x,0});
            it--;
            last=it->first;
        }else{
            last=tr.lower_bound({x+1,0})->first;
        }
        if(opt>=3&&opt<=6){
            ans^=last;
        }
    }
    write(ans);
    return 0;
}

【模板】重链剖分 / 树链剖分

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
#define ls (p<<1)
#define rs ((p<<1)+1)
using namespace std;
typedef int ll;
typedef long long lll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(ll x){
	if(x<0){
		x*=-1;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=1e5+5;
ll n,m,rt,mod,cnt=1,a[maxn],f[maxn],son[maxn],top[maxn],dep[maxn],siz[maxn],dfn[maxn],val[maxn],head[maxn<<1];
struct bian{
	ll to,nxt;
}e[maxn<<1];
struct node{
	ll l,r,sum,tag;
}d[maxn<<2];
void addb(ll u,ll v){
	e[++cnt].nxt=head[u];
	e[cnt].to=v;
	head[u]=cnt;
}
void dfs1(ll x,ll fa){
	f[x]=fa;
	dep[x]=dep[fa]+1;
	siz[x]=1;
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(y!=fa){
			dfs1(y,x);
			siz[x]+=siz[y];
			if(siz[son[x]]<siz[y]){
				son[x]=y;
			}
		}
	}
}
void dfs2(ll x,ll topf){
	top[x]=topf;
	dfn[x]=++cnt;
	val[cnt]=a[x];
	if(son[x]){
		dfs2(son[x],topf);
	}
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(y!=f[x]&&y!=son[x]){
			dfs2(y,y);
		}
	}
}
void pushup(ll p){
	d[p].sum=(d[ls].sum+d[rs].sum)%mod;
}
void pushdown(ll p){
	if(d[p].tag){
		d[ls].sum=(d[ls].sum+d[p].tag*(d[ls].r-d[ls].l+1))%mod;
		d[rs].sum=(d[rs].sum+d[p].tag*(d[rs].r-d[rs].l+1))%mod;
		d[ls].tag=(d[ls].tag+d[p].tag)%mod;
		d[rs].tag=(d[rs].tag+d[p].tag)%mod;
		d[p].tag=0;
	}
}
void build(ll p,ll x,ll y){
	d[p].l=x;
	d[p].r=y;
	if(x==y){
		d[p].sum=val[x]%mod;
		return;
	}
	ll mid=(x+y)>>1;
	build(ls,x,mid);
	build(rs,mid+1,y);
	pushup(p);
}
void add(ll p,ll x,ll y,ll k){
	if(d[p].l>=x&&d[p].r<=y){
		d[p].sum=(d[p].sum+k*(d[p].r-d[p].l+1))%mod;
		d[p].tag=(d[p].tag+k)%mod;
		return;
	}
	pushdown(p);
	ll mid=(d[p].l+d[p].r)>>1;
	if(mid>=x){
		add(ls,x,y,k);
	}
	if(mid<y){
		add(rs,x,y,k);
	}
	pushup(p);
}
ll query(ll p,ll x,ll y){
	if(d[p].l>=x&&d[p].r<=y){
		return d[p].sum;
	}
	pushdown(p);
	ll mid=(d[p].l+d[p].r)>>1,res=0;
	if(mid>=x){
		res=(res+query(ls,x,y))%mod;
	}
	if(mid<y){
		res=(res+query(rs,x,y))%mod;
	}
	return res;
}
void change1(ll x,ll y,ll k){
	while(top[x]!=top[y]){
		if(dep[f[top[x]]]<dep[f[top[y]]]){
			swap(x,y);
		}
		add(1,dfn[top[x]],dfn[x],k);
		x=f[top[x]];
	}
	if(dep[x]>dep[y]){
		swap(x,y);
	}
	add(1,dfn[x],dfn[y],k);
}
ll ask(ll x,ll y){
	ll res=0;
	while(top[x]!=top[y]){
		if(dep[f[top[x]]]<dep[f[top[y]]]){
			swap(x,y);
		}
		res=(res+query(1,dfn[top[x]],dfn[x]))%mod;
		x=f[top[x]];
	}
	if(dep[x]>dep[y]){
		swap(x,y);
	}
	res=(res+query(1,dfn[x],dfn[y]))%mod;
	return res;
}
int main(){
	n=rd();
	m=rd();
	rt=rd();
	mod=rd();
	for(ll i=1;i<=n;i++){
		a[i]=rd();
	}
	for(ll i=1;i<n;i++){
		ll u=rd(),v=rd();
		addb(u,v);
		addb(v,u);
	}
	cnt=0;
	dfs1(rt,0);
	dfs2(rt,rt);
	build(1,1,n);
	for(ll i=1;i<=m;i++){
		ll x=rd(),y,z;
		if(x==1){
			x=rd();
			y=rd();
			z=rd();
			change1(x,y,z);
		}else if(x==2){
			x=rd();
			y=rd();
			write(ask(x,y));
			putchar('\n');
		}else if(x==3){
			x=rd();
			z=rd();
			add(1,dfn[x],dfn[x]+siz[x]-1,z);
		}else{
			x=rd();
			write(query(1,dfn[x],dfn[x]+siz[x]-1));
			putchar('\n');
		}
	}
	return 0;
}

【模板】AC 自动机

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=2e6+5;
queue<ll> q;
ll n,cnt1,cnt2,mp[maxn],head[maxn];
struct node1{
    ll son[26],fail,sum;
}trie[maxn];
struct node2{
	ll to,nxt;
}ed[maxn<<1];
void insert(char *s,ll idx){
    ll now=0,len=strlen(s);
    for(ll i=0;i<len;i++){
        ll ch=s[i]-'a';
        if(!trie[now].son[ch]){
            trie[now].son[ch]=++cnt1;
        }
        now=trie[now].son[ch];
    }
    mp[idx]=now;
}
void getfail(){
    for(ll i=0;i<26;i++){
        if(trie[0].son[i]){
            q.push(trie[0].son[i]);
        }
    }
    while(!q.empty()){
        ll now=q.front();
        q.pop();
        for(ll i=0;i<26;i++){
            if(trie[now].son[i]){
                trie[trie[now].son[i]].fail=trie[trie[now].fail].son[i];
                q.push(trie[now].son[i]);
            }else{
                trie[now].son[i]=trie[trie[now].fail].son[i];
            }
        }
    }
}
void add(ll x,ll y){
    ed[++cnt2].to=y;
    ed[cnt2].nxt=head[x];
	head[x]=cnt2;
}
void dfs(ll x){
	for(ll i=head[x];i;i=ed[i].nxt){
		dfs(ed[i].to);
		trie[x].sum+=trie[ed[i].to].sum;
	}
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>n;
    char s[maxn],t[maxn];
    for(ll i=1;i<=n;i++){
        cin>>s;
        insert(s,i);
    }
    getfail();
    cin>>t;
    ll now=0,len=strlen(t);
    for(ll i=0;i<len;i++){
		now=trie[now].son[t[i]-'a'];
		trie[now].sum++;
	}
	for(ll i=1;i<=cnt1;i++){
		add(trie[i].fail,i);
    }
	dfs(0);
	for(ll i=1;i<=n;i++){
		cout<<trie[mp[i]].sum<<"\n";
	}
    return 0;
}

【模板】扩展 KMP / exKMP(Z 函数)

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string a,b,s;
ll n,m,k,pp,ans1,ans2,z[40000005];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>a>>b;
	s=b+"#"+a;
	n=a.size();
	m=b.size();
	k=s.size();
	for(ll i=1,l=0,r=0;i<=k;i++){
		if(i<=r){
			z[i]=min(r-i,z[i-l]);
		}else{
			z[i]=0;
		}
		while(s[z[i]]==s[z[i]+i]){
			z[i]++;
		}
		if(i+z[i]>r){
			l=i;
			r=i+z[i];
		}
	}
	z[0]=m;
	for(ll i=1;i<=m;i++){
		ans1^=i*(z[i-1]+1);
	}
	for(ll i=1;i<=n;i++){
		ans2^=i*(z[i+m]+1);
	}
	cout<<ans1<<"\n"<<ans2;
	return 0;
}

【模板】树上 K 级祖先

题目跳转

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef unsigned int ui;
typedef long long lll;
uint8_t buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
ll rd(){
	ll x=0,f=1,ch=gc();
	while(ch<'0'||ch>'9'){
		if(ch=='-'){
            f=-1;
        }
        ch=gc();
	}
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch-'0');
		ch=gc();
	}
	return x*f;
}
void write(lll x){
	if(x<0){
		x=-x;
		putchar('-');
	}
	if(x>9){
		write(x/10);
	}
	putchar(x%10+'0');
}
const ll maxn=5e5+5;
ui s;
lll ans;
ll n,q,rt,res,ecnt=1,cnt,head[maxn];
ll f[maxn],son[maxn],siz[maxn],dep[maxn],top[maxn],dfn[maxn],xu[maxn];
ui gets(ui x){
	x^=x<<13;
	x^=x>>17;
	x^=x<<5;
	return s=x;
}
struct enode{
	ll to,nxt;
}e[maxn<<1];
void adde(ll u,ll v){
	e[++ecnt].nxt=head[u];
	e[ecnt].to=v;
	head[u]=ecnt;
}
void dfs1(ll x,ll fa){
	f[x]=fa;
	dep[x]=dep[fa]+1;
	siz[x]=1;
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(y!=fa){
			dfs1(y,x);
			siz[x]+=siz[y];
			if(siz[y]>siz[son[x]]){
				son[x]=y;
			}
		}
	}
}
void dfs2(ll x,ll topf){
	top[x]=topf;
	dfn[x]=++cnt;
	xu[cnt]=x;
	if(son[x]){
		dfs2(son[x],topf);
	}
	for(ll i=head[x];i;i=e[i].nxt){
		ll y=e[i].to;
		if(y!=f[x]&&y!=son[x]){
			dfs2(y,y);
		}
	}
}
ll query(ll x,ll k){
	while(dfn[x]-dfn[top[x]]<k){
		k-=dfn[x]-dfn[top[x]]+1;
		x=f[top[x]];
	}
	return xu[dfn[x]-k];
}
int main(){
	n=rd();
	q=rd();
	s=rd();
	for(ll i=1;i<=n;i++){
		ll x=rd();
		if(x){
			adde(x,i);
			adde(i,x);
		}else{
			rt=i;
		}
	}
	dfs1(rt,0);
	dfs2(rt,rt);
	for(ll i=1;i<=q;i++){
		ll x=(gets(s)^res)%n+1;
		ll k=(gets(s)^res)%dep[x];
		res=query(x,k);
		ans^=(lll)res*i;
	}
	write(ans);
	return 0;
}

本文是作者收集的洛谷上的模板题以及自己的代码,将会持续更新,你的点赞与关注将是我更新的最大动力!
如果您觉得有不正确或不妥的地方,欢迎在评论区指正,感谢!
如果觉得对你有帮助,就帮忙点个赞吧!(❁´◡`❁)