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