CSP-S rp+++++++++++
数据结构~
01trie~
int t[N*31][2],nv=1;
void build(int p,int d,int v){
bool flag=(v&(1<<d));
if(!t[p][flag]) t[p][flag]=++nv;
if(d) build(t[p][flag],d-1,v);
}
int query(int p,int d,int v){
if(d<0) return 0;
bool flag=(v&(1<<d));
if(t[p][!flag]) return (1<<d)+query(t[p][!flag],d-1,v);
if(t[p][flag]) return query(t[p][flag],d-1,v);
}
ST表
#include <bits/stdc++.h>
using namespace std;
const int logn = 21;
const int maxn = 2000001;
int f[maxn][logn + 1], Logn[maxn + 1];
int read() { // 快读
char c = getchar();
int x = 0, f = 1;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
void pre() { // 准备工作,初始化
Logn[1] = 0;
Logn[2] = 1;
for (int i = 3; i < maxn; i++) {
Logn[i] = Logn[i / 2] + 1;
}
}
int main() {
int n = read(), m = read();
for (int i = 1; i <= n; i++) f[i][0] = read();
pre();
for (int j = 1; j <= logn; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); // ST表具体实现
for (int i = 1; i <= m; i++) {
int x = read(), y = read();
int s = Logn[y - x + 1];
printf("%d\n", max(f[x][s], f[y - (1 << s) + 1][s]));
}
return 0;
}
树状数组
#define lower_bit(x) (x)&-(x)
using namespace std;
int n,m,tree[200000+10];
void add(int a,int c){
for(int i=a;i<=n;i+=lower_bit(i))tree[i]+=c;
}
int find(int r){
int ret=0;
for(int i=r;i>=1;i-=lower_bit(i))ret+=tree[i];
return ret;
}
线段树~
void addtag(int iSeg,int val){
tr[iSeg].tag+=val;
tr[iSeg].sum+=(tr[iSeg].r-tr[iSeg].l+1)*val;
}
void pushup(int iSeg){
tr[iSeg].sum=tr[lsp].sum+tr[rsp].sum;
}
void pushdown(int iSeg){
addtag(lsp,tr[iSeg].tag);
addtag(rsp,tr[iSeg].tag);
tr[iSeg].tag=0;
}
void build(int iSeg,int l,int r){
tr[iSeg].l=l; tr[iSeg].r=r;
if(l==r){
tr[iSeg].sum=x[l];
tr[iSeg].tag=0;
return;
}
int mid=l+(r-l)/2;
build(lsp,l,mid); build(rsp,mid+1,r);
pushup(iSeg);
}
void modify(int iSeg,int l,int r,int val){
if(l<=tr[iSeg].l&&tr[iSeg].r<=r){
addtag(iSeg,val);
return;
}
pushdown(iSeg);
if(l<=tr[lsp].r)modify(lsp,l,r,val);
if(tr[rsp].l<=r)modify(rsp,l,r,val);
pushup(iSeg);
}
int query(int iSeg,int l,int r){
// cout<<iSeg<<" "<<l<<" "<<r<<" "<<tr[iSeg].l<<" "<<tr[iSeg].r<<endl;
if(l<=tr[iSeg].l&&tr[iSeg].r<=r) return tr[iSeg].sum;
pushdown(iSeg);
int sum=0;
if(l<=tr[lsp].r)sum+=query(lsp,l,r);
if(tr[rsp].l<=r)sum+=query(rsp,l,r);
return sum;
}
fhq treap~
mt19937 rnd(time(0));
const int Max_n=1e6+10;
class Node{
public:
int l_son=0,r_son=0;
int val,ind,size=0;
Node(){
l_son=r_son=size=0;
}
};
class treap{
public:
int size,root;
Node fhq[Max_n];
int new_node(int x){
fhq[++size].val=x;
fhq[size].ind=rnd();
fhq[size].l_son=fhq[size].r_son=0;
fhq[size].size=1;
return size;
}
treap(){
size=0,root=0;
}
void push_up(int x){
fhq[x].size=fhq[fhq[x].l_son].size+fhq[fhq[x].r_son].size+1;
}
void split(int x,int k,int &l,int &r){
if(!x){
l=r=0;
return;
}else if(fhq[x].val<=k){l=x;split(fhq[x].r_son,k,fhq[x].r_son,r);}
else{r=x;split(fhq[x].l_son,k,l,fhq[x].l_son);}
push_up(x);
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(fhq[x].ind>fhq[y].ind){
fhq[x].r_son=merge(fhq[x].r_son,y);
push_up(x);
return x;
}else{
fhq[y].l_son=merge(x,fhq[y].l_son);
push_up(y);
return y;
}
}
void insert(int val){
int a,b=0;
split(root,val,a,b);
root=merge(merge(a,new_node(val)),b);
}
void del(int val){
int a,b,c=0;
split(root,val,a,b);
split(a,val-1,a,c);
c=merge(fhq[c].l_son,fhq[c].r_son);
root=merge(merge(a,c),b);
}
int get_rnk(int val){
int a,b;
split(root,val-1,a,b);
int ret=fhq[a].size;
root=merge(a,b);
return ret+1;
}
int get_num(int rnk){
int now=root;
while(now){
if(fhq[fhq[now].l_son].size+1==rnk)break;
else if(fhq[fhq[now].l_son].size+1>rnk)now=fhq[now].l_son;
else{
rnk-=fhq[fhq[now].l_son].size+1;
now=fhq[now].r_son;
}
}
return fhq[now].val;
}
int pre(int val){
int a,b=0;
split(root,val-1,a,b);
int now=a;
while(fhq[now].r_son)now=fhq[now].r_son;
int pr=fhq[now].val;
root=merge(a,b);
return pr;
}
int sub(int val){
int a,b=0;
split(root,val,a,b);
int now=b;
while(fhq[now].l_son)now=fhq[now].l_son;
int su=fhq[now].val;
root=merge(a,b);
return su;
}
};
数学
快速幂
int pw(int a,int b){
int res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
逆元+Lucas
int ny[N],jc[N],jcny[N];
void init(){
ny[1]=1;
for(int i=2;i<N;i++) ny[i]=(mod-mod/i)*ny[mod%i]%mod;
jcny[0]=jcny[1]=1;
for(int i=2;i<N;i++) jcny[i]=jcny[i-1]*ny[i]%mod;
jc[0]=jc[1]=1;
for(int i=2;i<N;i++) jc[i]=jc[i-1]*i%mod;
}
int c(int a,int b){
if(b>a) return 0;
return jc[a]*jcny[a-b]%mod*jcny[b]%mod;
}
/*
int lucas(int a,int b){
if(!b) return 1;
return c(a%mod,b%mod)*lucas(a/mod,b/mod)%mod;
}
*/
exgcd
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
埃氏筛
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
除法分块
for(int l=1,r;l<=n;l=r+1){
r=(n/(n/l));
cout<<(n/l)<<' '<<(r-l+1)<<endl;
}
扫描线
#include <stdio.h>
#include <iostream>
#include <algorithm>
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
const int MAXN = 1e6 + 10;
typedef long long ll;
int n, cnt = 0;
ll x1, y1, x2, y2, X[MAXN << 1];
struct ScanLine {
ll l, r, h;
int mark;
// mark用于保存权值 (1 / -1)
bool operator < (const ScanLine &rhs) const {
return h < rhs.h;
}
} line[MAXN << 1];
struct SegTree {
int l, r, sum;
ll len;
// sum: 被完全覆盖的次数;
// len: 区间内被截的长度。
} tree[MAXN << 2];
void build_tree(int x, int l, int r) {
// 我觉得最不容易写错的一种建树方法
tree[x].l = l, tree[x].r = r;
tree[x].len = 0;
tree[x].sum = 0;
if(l == r)
return;
int mid = (l + r) >> 1;
build_tree(lson, l, mid);
build_tree(rson, mid + 1, r);
return;
}
void pushup(int x) {
int l = tree[x].l, r = tree[x].r;
if(tree[x].sum /* 也就是说被覆盖过 */ )
tree[x].len = X[r + 1] - X[l];
// 更新长度
else
tree[x].len = tree[lson].len + tree[rson].len;
// 合并儿子信息
}
void edit_tree(int x, ll L, ll R, int c) {
int l = tree[x].l, r = tree[x].r;
// 注意,l、r和L、R的意义完全不同
// l、r表示这个节点管辖的下标范围
// 而L、R则表示需要修改的真实区间
if(X[r + 1] <= L || R <= X[l])
return;
// 这里加等号的原因:
// 假设现在考虑 [2,5], [5,8] 两条线段,要修改 [1,5] 区间的sum
// 很明显,虽然5在这个区间内,[5,8] 却并不是我们希望修改的线段
// 所以总结一下,就加上了等号
if(L <= X[l] && X[r + 1] <= R) {
tree[x].sum += c;
pushup(x);
return;
}
edit_tree(lson, L, R, c);
edit_tree(rson, L, R, c);
pushup(x);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%lli %lli %lli %lli", &x1, &y1, &x2, &y2);
X[2 * i - 1] = x1, X[2 * i] = x2;
line[2 * i - 1] = (ScanLine) {x1, x2, y1, 1};
line[2 * i] = (ScanLine) {x1, x2, y2, -1};
// 一条线段含两个端点,一个矩形的上下边都需要扫描线扫过
}
n <<= 1;
// 直接把 n <<= 1 方便操作
sort(line + 1, line + n + 1);
sort(X + 1, X + n + 1);
int tot = unique(X + 1, X + n + 1) - X - 1;
// 去重最简单的方法:使用unique!(在<algorithm>库中)
build_tree(1, 1, tot - 1);
// 为什么是 tot - 1 :
// 因为右端点的对应关系已经被篡改了嘛…
// [1, tot - 1]描述的就是[X[1], X[tot]]
ll ans = 0;
for(int i = 1; i < n /* 最后一条边是不用管的 */ ; i++) {
edit_tree(1, line[i].l, line[i].r, line[i].mark);
// 先把扫描线信息导入线段树
ans += tree[1].len * (line[i + 1].h - line[i].h);
// 然后统计面积
}
printf("%lli", ans);
return 0;
}
字符串
AC自动机(/KMP)
struct kkk{
int son[26],fail,flag,ans;
void clear(){memset(son,0,sizeof(son)),fail=flag=ans=0;}
}trie[maxn];
queue<int>q;
void insert(char* s,int num){
int u=1,len=strlen(s);
for(int i=0;i<len;i++){
int v=s[i]-'a';
if(!trie[u].son[v])trie[u].son[v]=++cnt;
u=trie[u].son[v];
}
if(!trie[u].flag)trie[u].flag=num;
Map[num]=trie[u].flag;
}
void getFail(){
for(int i=0;i<26;i++)trie[0].son[i]=1;
q.push(1);
while(!q.empty()){
int u=q.front();q.pop();
int Fail=trie[u].fail;
for(int i=0;i<26;i++){
int v=trie[u].son[i];
if(!v){trie[u].son[i]=trie[Fail].son[i];continue;}
trie[v].fail=trie[Fail].son[i]; in[trie[v].fail]++;
q.push(v);
}
}
}
void topu(){
for(int i=1;i<=cnt;i++)
if(in[i]==0)q.push(i);
while(!q.empty()){
int u=q.front();q.pop();vis[trie[u].flag]=trie[u].ans;
int v=trie[u].fail;in[v]--;
trie[v].ans+=trie[u].ans;
if(in[v]==0)q.push(v);
}
}
void query(char* s){
int u=1,len=strlen(s);
for(int i=0;i<len;i++)
u=trie[u].son[s[i]-'a'],trie[u].ans++;
}
图论
链式前向星
struct edge{int to,w,nxt;}e[M*2];
int hed[N],ecnt;
void add(int l,int r,int c){
e[++ecnt]=(edge){r,c,hed[l]};
hed[l]=ecnt;
}
dijkstra
struct edge{int to,w;};
vector<edge> e[N];
struct node{
int u,d;
bool operator<(const node&tmp)const{return d>tmp.d;}
};
priority_queue<node> q;
int dis[N];
bool vis[N];
void dijkstra(){
memset(dis,0x3f,sizeof dis);
q.push((node){s,0});
dis[s]=0;
while(!q.empty()){
int u=q.top().u;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=0;i<e[u].size();i++){
int v=e[u][i].to,cost=dis[u]+e[u][i].w;
if(dis[v]>cost){
dis[v]=cost;
q.push((node){v,cost});
}
}
}
}
熟练剖粪树链剖分+树链剖分LCA
void dfs(int u,int f){
size[u]=1;
for(int &v:V[u]){
if(v!=f){
fa[v]=u,deep[v]=deep[u]+1;dfs(v,u);size[u]+=size[v];
if(size[v]>=size[hson[u]])hson[u]=v,swap(v,V[u][0]);
}
}
}
void dfs2(int u,int f,int tp){
dfn[u]=cnt++,rnk[dfn[u]]=u,top[u]=tp;
for(int &v:V[u]){
if(v!=f){if(hson[u]==v)dfs2(v,u,tp);else dfs2(v,u,v);}
}
}
int LCA(int a,int b){
while(top[a]!=top[b]){
if(deep[top[b]]>deep[top[a]])swap(a,b);
a=fa[top[a]];
}
return deep[a]>deep[b]?b:a;
}
倍增LCA
void dfs(int root, int fno) {
fa[root][0] = fno;
dep[root] = dep[fa[root][0]] + 1;
for (int i = 1; i < 31; ++i) {
fa[root][i] = fa[fa[root][i - 1]][i - 1];
cost[root][i] = cost[fa[root][i - 1]][i - 1] + cost[root][i - 1];
}
int sz = v[root].size();
for (int i = 0; i < sz; ++i) {
if (v[root][i] == fno) continue;
cost[v[root][i]][0] = w[root][i];
dfs(v[root][i], root);
}
}
int lca(int x, int y) {
if (dep[x] > dep[y]) swap(x, y);
int tmp = dep[y] - dep[x], ans = 0;
for (int j = 0; tmp; ++j, tmp >>= 1)
if (tmp & 1) ans += cost[y][j], y = fa[y][j];
if (y == x) return ans;
for (int j = 30; j >= 0 && y != x; --j) {
if (fa[x][j] != fa[y][j]) {
ans += cost[x][j] + cost[y][j];
x = fa[x][j];
y = fa[y][j];
}
}
ans += cost[x][0] + cost[y][0];
return ans;
}
拓扑排序
bool toposort() {
vector<int> L;
queue<int> S;
for (int i = 1; i <= n; i++)
if (in[i] == 0) S.push(i);
while (!S.empty()) {
int u = S.front();
S.pop();
L.push_back(u);
for (auto v : G[u]) {
if (--in[v] == 0) {
S.push(v);
}
}
}
if (L.size() == n) {
for (auto i : L) cout << i << ' ';
return true;
} else {
return false;
}
}
MST
for(int i=1;i<=n;i++)fa[i]=i;
while(!Q1.empty()){
auto [c,u,v]=Q1.top();Q1.pop();
if(find(u)==find(v))continue;
if(!(n--)||!(k--))break;
add(u,v);
ans=max(ans,c);
}
dinic
int n,m,s,t,u,v,dis[N],hed[N],rad[N];
struct edge{int to,w,nxt;}e[M*2];
int ecnt=1;
void add(int u,int v,int w){
e[++ecnt]=(edge){v,w,hed[u]};
hed[u]=ecnt;
}
void link(int u,int v,int w){
add(u,v,w);
add(v,u,0);
}
bool bfs(){
queue<int> q;
for(int i=s;i<=t;i++) dis[i]=-1;
dis[s]=0;
q.push(s);
while(!q.empty()){
int cur=q.front();
rad[cur]=hed[cur];
q.pop();
for(int i=hed[cur];i;i=e[i].nxt){
if(dis[e[i].to]==-1&&e[i].w){
dis[e[i].to]=dis[cur]+1;
q.push(e[i].to);
}
}
}
return dis[t]!=-1;
}
int dfs(int x,int flow){
if(x==t) return flow;
int cnt=0;
for(int i=rad[x];i&&flow;i=e[i].nxt){
rad[x]=i;
if(dis[e[i].to]==dis[x]+1&&e[i].w){
int ret=dfs(e[i].to,min(flow,e[i].w));
if(ret>0){
e[i].w-=ret;
e[i^1].w+=ret;
cnt+=ret;
flow-=ret;
}
}
}
return cnt;
}
MCMF
int n,m,s,t,dis[N],hed[N],rad[N],ans1,ans2;
bool vis[N];
struct edge{int to,w,c,nxt;}e[M*2];
int ecnt=1;
void add(int u,int v,int w,int c){
e[++ecnt]=(edge){v,w,c,hed[u]};
hed[u]=ecnt;
}
void link(int u,int v,int w,int c){
add(u,v,w,c);
add(v,u,0,-c);
}
#define TO e[i].to
#define COST dis[x]+e[i].c
bool spfa(){
for(int i=s;i<=t;i++) dis[i]=1e9;
for(int i=s;i<=t;i++) vis[i]=0;
queue<int> q;
q.push(s);
vis[s]=1,dis[s]=0;
while(!q.empty()){
int x=q.front();
rad[x]=hed[x];
q.pop();
vis[x]=0;
for(int i=hed[x];i;i=e[i].nxt)if(dis[TO]>COST&&e[i].w){
dis[TO]=COST;
if(!vis[TO]){
q.push(TO);
vis[TO]=1;
}
}
}
return dis[t]!=1e9;
}
int dfs(int x,int flow){
if(x==t) return flow;
vis[x]=1;
int cnt=0;
for(int i=rad[x];i&&flow;i=e[i].nxt){
rad[x]=i;
if(!vis[TO]&&dis[TO]==COST&&e[i].w){
int ret=dfs(TO,min(flow,e[i].w));
e[i].w-=ret;
e[i^1].w+=ret;
cnt+=ret;
flow-=ret;
ans2+=ret*e[i].c;
}
}
vis[x]=0;
return cnt;
}
标签:return,int,root,void,son,整理,fhq,CSP,模板
From: https://www.cnblogs.com/baoziawa/p/18503304