首页 > 其他分享 >CSP-S 可能出现的模板(非原创,各个地方整理得)

CSP-S 可能出现的模板(非原创,各个地方整理得)

时间:2024-10-25 21:42:25浏览次数:6  
标签:return int root void son 整理 fhq CSP 模板

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

相关文章

  • Tarjan连通性算法模板大整合
    更新日志前言由于Tarjan算法页面过多,这里统一做一个整合,后期可能还会加入或者更改这里的模板。另外的,这个页面只提供模板——以及链接,详细讲解点链接即可。强连通(有向图,储存每个节点属于的分量编号)intscnt;intscc[N],siz[N];intdcnt;intdfn[N],low[N];boolins[N......
  • C++之内存管理与模板初级
    内容介绍Ⅰ.C++内存管理1.C/C++内存分布2.C与C++动态内存管理方式对比2.1C中动态内存管理方式2.2C++中内存管理方式3.new和delete的底层实现原理(了解)Ⅱ.模板初阶1.模板介绍2.函数模板3.函数模板参数匹配原则4.类模板Ⅰ.C++内存管理1.C/C++内存分布intn1=1;......
  • 2024CSP游记
    2024CSP游记众所周知,2024CSP第二轮非专业组能力等级认证将于2024.10.26(星期六)举行关于本人初中生,今年第一次参加CSP的复赛。赛前赛前一星期,教练让我们每天都到机房训练,整整一星期。文化课pass作业pass共做10+套模拟出行状况&&时间线本人坐标ZJ,考点在杭州师范大学(下沙校......
  • CSP2024 游记 - 未完
    CSP2024游记\[written\by:\mathbb{CMRHHH}\]此时:2024/10/25;18:30;路途颠簸,作业先不写了吧……有些晕了,正在听杰伦的仙乐;CCF真长策,赚得英雄尽白头,转眼已是第三年征战CSP-S了。当年一起打的同学都还在打啊,初赛去北师大附中的时候碰到了想碰到的两位巨佬——一尊去了温中......
  • CSP2023游寄
    没啥好说的,寄了。快来嘲讽这个pj130tg115的小丑罢。upd:pj挂成了105,这下tg比pj还高了,乐。在CSP2024的前夕,我想了想,还是决定把这个唐诗游记写出来。J8:30开考。看T1,马上往数学方面想,但是想了一会没想出来。这时旁边的小朋友已经开始测T2了,有点慌。强迫自......
  • 浅拷贝与深拷贝 以及嵌套和递归使用模板类
     1.浅拷贝和深拷贝——对象和类浅拷贝浅拷贝只复制对象的基本属性,而不复制引用类型的属性指向的对象,即只复制引用而不复制引用指向的对象在浅拷贝中,新对象与原始对象共享引用类型的属性指向的对象,即它们指向同一个对象。编译器提供的拷贝构造函数是浅拷贝,当一个对象修......
  • Java基础第五天(实训学习整理资料(五)练习题)
    目录1、百钱买百鸡2、搬砖问题3、(循环)**求水仙花数。4、完数5、费波那契,兔子数列6、打渔还是晒网1、百钱买百鸡(for循环)*“百钱买百鸡”是我国古代的著名数学题。题目这样描述:5文钱可以买1只公鸡,3文钱可以买一只母鸡,1文钱可以买3只小鸡。用100文钱买100只鸡......
  • [计划] CSP-S2 2024 考前复习
    怎么算空间???复习板子floydcrtecgcd单调队列prim(kruskal求最小生成树)并查集各种写法、复杂度区间加区间和BITBIT注意位置是否会到0FHQ-TreapFHQ-Treap勿把Split_Val和Split_Siz写混;FHQ-Treap记得Split时PushUp注意FHQ-Treap初值问题字符串哈希区间......
  • 2024最新互联网工程师 Java 面试八股文及答案整理
    2024金九银十即将结束,竟很多同学会问Java面试八股文有必要背吗?!!我的回答是:很有必要!!!!你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂。国内的互联网面试,恐怕是现存的、最接近科举考试的制度。而且,我国的八股文确实是独树一帜。以美国为例,北美工程师面试比较重视算......
  • 一图胜千言,PPT中的数据分析模板样式
    PPT中数据可视化是一种将数据以图形或图表的形式展示出来的方法,它可以帮助观众更直观地理解数据所传达的信息。数据可视化是一个不断发展的领域,随着技术的进步,新的工具和方法不断出现,使得数据的呈现更加直观和互动。在笔格PPT,选择合适的样式模板便可直接制作图表,小编带来了各......