模板集合

hello~ 这里是nihachu(叫niki就好)!

这里是各种算法的模板集合,主要是方便自己背板子用的,后续会不定期更新,希望能帮到和我一样的小伙伴,也希望各路大神可以帮忙指正或补充,thanks~

(部分代码来自网络,若有侵权,请联系我删除,感谢!)

动态规划:

01背包(已降维)

for(int i = 1; i <= n; i ++){
	for(int j = m; i >= w[i]; j --){
		dp[j] = max(dp[j],dp[j - w[i]] + v[i]);
	}
}

完全背包

for(int i = 1; i <= n ; i ++){
	for(int j = w[i]; i <= m; j ++){
		dp[j] = max(dp[j],dp[j - w[i]] + v[i]);
	}
}

背包计数

for(int i = 1; i <= n; i ++){
	for(int j = m; i >= w[i]; j --){
		dp[j] += dp[j - w[i]];
	}
}

(若要求恰好为m,则dp[0]初始化为1,其他均为0);

二进制拆分(用于多重背包)

for(int i = 1; i <= n1; i ++){
	scanf("%d %d %d",&a, &b, &c);
	for(int k = 1; k <= c; k <<= 1){
		v[++u] = k * a; w[u] = k * b;
		c -= k;
	}
	if(c) v[++u] = a * c,w[u] = b * c;
}

树上背包

//siz为体积,val为点权
void dfs(int x){
	for(int i = siz[x]; i <= m; i ++) dp[x][i] = val[x];
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		dfs(v);
		for(int u = m - siz[x]; u >= 0; u --){
			for(int k = 0; k <= u; k ++){
				dp[x][u + siz[x]] = max(dp[x][u + siz[x]],dp[x][u + siz[x] - k] + dp[v][k]);
			}	
		}
	}
}

或者

memset(dp,-0x3f,sizeof(dp));
void dfs(int x){
	for(int i = 1; i <= m; i ++) dp[x][i] = v[x];
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		dfs(v);
		for(int u = m; u >= 1; u --){
			for(int k = 0; k <= u; k ++){
				dp[x][u] = max(dp[x][u],dp[x][u - k] + dp[v][k]);
			}
		}
	}
}

时间优化

快读

int read()
{
   int 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*10+ch-'0',ch=getchar();
   return x*f;
}

快写

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

手动o2优化

-std=c++11 -O2

超级快读

struct IO {
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
  char buf[MAXSIZE], *p1, *p2;
  char pbuf[MAXSIZE], *pp;
#if DEBUG
#else
  IO() : p1(buf), p2(buf), pp(pbuf) {}

  ~IO() { fwrite(pbuf, 1, pp - pbuf, stdout); }
#endif
  char gc() {
#if DEBUG  // 调试,可显示字符
    return getchar();
#endif
    if (p1 == p2) p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
    return p1 == p2 ? ' ' : *p1++;
  }

  bool blank(char ch) {
    return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
  }

  template <class T>
  void read(T &x) {
    double tmp = 1;
    bool sign = 0;
    x = 0;
    char ch = gc();
    for (; !isdigit(ch); ch = gc())
      if (ch == '-') sign = 1;
    for (; isdigit(ch); ch = gc()) x = x * 10 + (ch - '0');
    if (ch == '.')
      for (ch = gc(); isdigit(ch); ch = gc())
        tmp /= 10.0, x += tmp * (ch - '0');
    if (sign) x = -x;
  }

  void read(char *s) {
    char ch = gc();
    for (; blank(ch); ch = gc());
    for (; !blank(ch); ch = gc()) *s++ = ch;
    *s = 0;
  }

  void read(char &c) { for (c = gc(); blank(c); c = gc()); }

  void push(const char &c) {
#if DEBUG  // 调试,可显示字符
    putchar(c);
#else
    if (pp - pbuf == MAXSIZE) fwrite(pbuf, 1, MAXSIZE, stdout), pp = pbuf;
    *pp++ = c;
#endif
  }

  template <class T>
  void write(T x) {
    if (x < 0) x = -x, push('-');  // 负数输出
    static T sta[35];
    T top = 0;
    do {
      sta[top++] = x % 10, x /= 10;
    } while (x);
    while (top) push(sta[--top] + '0');
  }

  template <class T>
  void write(T x, char lastChar) {
    write(x), push(lastChar);
  }
} io;

io.read(n);
io.write(n,'\n');

图论

链式前向星

void add(int x, int y){
	to[++cnt] = y;
	nxt[cnt] = head[x];
	head[x] = cnt;
}

图的遍历

dfs:

void dfs(int x){
   vis[x] = 1; 
   printf("%d\n",x);
   for(int i = head[x];i;i = nxt[i])
	if(!vis[to[i]]) dfs(to[i]);
}

bfs :

void bfs(int x){
	z[++top] = x;
   for(int i = 1; i <= top; i ++){
     int now = z[top ++];
     printf("%d\n",now);
     for(int j = head[now]; j; j = nxt[j]){
     	if(!vis[to[j]])
        vis[to[j]] = 1, z[++top] = to[j];
     }
}

欧拉路径/回路

1)判断是不是欧拉路径/回路

for(int i = 64; i <= 125; i ++){
		if(du[i] % 2)  jud ++ ; //记录入度为奇数的点
	}
   if(!jud) //是欧拉回路
   if(jud == 2) //是欧拉路径
   if(jud && jud != 2)//啥也不是
}

2)欧拉路径/回路的遍历

void dfs(int x){
	for(int i = head[x]; i; i = nxt[i])
    if(!vis[i]) vis[i] = 1, dfs(to[i]);
   printf("%d",x);
   }

3)遍历环并记录长度

void dfs(int x,int dt){
	if(vis[x]){
		ans = min(ans,dt - d[x]);
	}
	else{
		vis[x] = true;
		d[x] = dt;
		dfs(to[x],dt + 1);
	}
}

拓扑排序

for(int i = 1; i <= n ; i ++) if(du[i] == 0) z[++top];
for(int i = 1; i <= top; i ++){
	for(int j = head[z[i]]; j; j = nxt[j]){
		du[to[j]] --;
        if(du[to[j]] == 0) z[++top] = to[j];
    }
}

dj

void dj(int u){
	memset(dis,0x3f,sizeof(dis));
	q.push({u,0});
	dis[u] = 0;
	while(!q.empty()){
		int x = q.top().x;
		q.pop();
		if(vis[x]) continue;
		vis[x] = 1;
		for(int i = head[x]; i; i = nxt[i]){
			int v = to[i];
			if(dis[v] > dis[x] + 1){
				dis[v] = dis[x] + 1;
				q.push({v,dis[v]});
			}
		}
	}
}

spfa(判负环)

bool spfa(int s){
	queue<int> q;
	memset(dis,0x3f,sizeof(dis));
	dis[s] = 0;
	q.push(s);
	while(!q.empty()){
		int x = q.front();
		q.pop();
		vis[x] = 0;
		for(int i = head[x]; i; i = nxt[i]){
			int t = to[i];
			if(dis[t] > dis[x] + v[i]){
				dis[t] = dis[x] + v[i];
				if(!vis[t]){
					vis[t] = 1;
					q.push(t);
					gt[t] ++;
				}
				if(gt[t] > n) return true;
			}
		}
	}
	return false;
}

kruskal

void kruskal(){
	sort(e + 1, e + m + 1, cmp);
	for(int i = 1; i <= n; i ++) fa[i] = i;	 
	for(int i = 1; i <= m; i ++){
		int r1 = find(e[i].x);
		int r2 = find(e[i].y);
		if(r1 == r2) continue;
		fa[r1] = r2;
		ans += e[i].z;
		tot = max(tot,e[i].z);
		cnt ++;
		if(cnt == n - 1) break;
	}
}

倍增求LCA


void dfs(int s, int fath){
	f[s][0] = fath;
	dep[s] = dep[fath] + 1;
	for(int u = 1; u <= 20; u ++){
		f[s][u] = f[f[s][u - 1]][u - 1];
	}
	for(int i = head[s]; i; i = nxt[i]){
		int t = to[i];
		if(t == fath) continue;
		dis[t] = dis[s] + v[i];
		dfs(t,s);
	}
}

int lca(int x, int y){
	if(dep[x] < dep[y]){
		swap(x,y);
	}
	for(int i = 20; i >= 0; i --){
		if(dep[f[x][i]] >= dep[y]) x = f[x][i];
	}
	if(x == y) return x;
	for(int i = 20; i >= 0; i --){
		if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
	}
	return f[x][0];
}

void ask(int x, int y, int lca){
	printf("%d\n",dis[x] + dis[y] - 2 * dis[lca]);
	return;
}

tarjan

void tarjan(int u){
	dfn[u] = low[u] = ++dfs_clock;
	s.push(u);
	for(int i = head[u]; i; i = nxt[i]){
		int v = to[i];
		if(!dfn[v]){
			tarjan(v);
			low[u] = min(low[u],low[v]);
		}
		else if(!sccnum[v]) low[u] = min(low[u], dfn[v]);
	}
	if(low[u] == dfn[u]){
		scccnt ++;
		while(1){
			int x = s.top();
			s.pop();
			sccnum[x] = scccnt;
			sccsu[scccnt] += w[x];
//			sccsz[scccnt] ++;
			if(x == u) break;
		}
	}
}

tarjan + 拓扑排序 + dp

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int dfn[N],low[N],sccnum[N],sccsu[N],sccsz[N],scccnt,dfs_clock;
int head[N],nxt[N],to[N],cnt;
int afhe[N],afnx[N],afto[N],afcnt;
stack <int> s;
int n, m, du[N], val[N], v[N], w[N], ans;
queue<int> q;

void add(int x, int y){
	to[++cnt] = y;
	nxt[cnt] = head[x];
	head[x] = cnt;
}

void afad(int x, int y){
	afto[++afcnt] = y;
	afnx[afcnt] = afhe[x];
	afhe[x] = afcnt;
}

void tarjan(int u){
	dfn[u] = low[u] = ++dfs_clock;
	s.push(u);
	for(int i = head[u]; i; i = nxt[i]){
		int v = to[i];
		if(!dfn[v]){
			tarjan(v);
			low[u] = min(low[u],low[v]);
		}
		else if(!sccnum[v]) low[u] = min(low[u], dfn[v]);
	}
	if(low[u] == dfn[u]){
		scccnt ++;
		while(1){
			int x = s.top();
			s.pop();
			sccnum[x] = scccnt;
			sccsu[scccnt] += w[x];
//			sccsz[scccnt] ++;
			if(x == u) break;
		}
	}
}

void afbuild(){
	for(int i = 1; i <= n; i ++){
		for(int u = head[i]; u; u = nxt[u]){
			int v1 = to[u];
			if(sccnum[i] != sccnum[v1]){
				afad(sccnum[i],sccnum[v1]);
//				printf("%d %d %d %d e\n",i,v1,sccnum[i],sccnum[v1]);
				++du[sccnum[v1]];
			}
		}
	}
}

void topo(){
	for(int i = 1; i <= scccnt; i ++) if(du[i] == 0) q.push(i), val[i] += sccsu[i];
	while(!q.empty()){
		int x = q.front();
		q.pop();
//		printf("x = %d, val = %d\n",x,val[x]);
		for(int i = afhe[x]; i; i = afnx[i]){
			int v1 = afto[i];
			du[v1] --;
//			printf("%d %d\n",val[v1],val[x] + sccsu[v1]);
			val[v1] = max(val[v1],val[x] + sccsu[v1]);
//			printf("v1 = %d, val = %d\n",v1,val[v1]);
			if(du[v1] == 0){
				q.push(v1);
			}
		}
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n ; i ++)
	scanf("%d",&w[i]);
//	return 0;
	for(int i = 1, u, v; i <= m ; i ++){
		scanf("%d%d",&u,&v);
		add(u,v);
	}
//	return 0;
	for(int i = 1; i <= n ; i ++){
		if(!dfn[i]) tarjan(i);
	}
//	for(int i = 1; i <= n ; i ++){
//		printf("i = %d, sccnum = %d\n",i,sccnum[i]);
//	}
//	for(int i = 1; i <= scccnt; i ++){
//		printf("num = %d, sum = %d\n",i,sccsu[i]);
//	}
	afbuild();
	topo();
	for(int i = 1; i <= scccnt; i ++) ans = max(ans,val[i]);
	printf("%d\n",ans);
	return 0;
}
			

求割点

void tarjan(int u, int anc){
	dfn[u] = low[u] = ++dfn_clock;
	s.push(u);
	int child = 0;
	for(int i = head[u]; i; i = nxt[i]){
		int v = to[i];
		if(!dfn[v]){
			tarjan(v,anc);
			low[u] = min(low[u], low[v]);
			if(low[v] >= dfn[u] && u != anc) cut[u] = 1;
			if(u == anc) child ++;
		}
		else if(!sccnum[v]){
			low[u] = min(low[u],dfn[v]);
		}
	}
	if(dfn[u] == low[u]){
		++scccnt;
		while(1){
			int x = s.top();
			s.pop();
			sccnum[x] = scccnt;
			if(x == u) break;
		}
	}
	// printf("%d %d %d %d %d\n",u,anc,dfn[u],low[u],child);
	if(child >= 2 && u == anc) cut[u] = 1;	
}

树剖

struct node{
	long long sum,tag;
};
node tr[4 * N];

void pushup(int p){
	tr[p].sum = tr[p * 2].sum + tr[p * 2 + 1].sum;
	tr[p].sum %= mod;
}

void pushdown(int p, int s, int t){
    int mid = (s + t) / 2;
    tr[p * 2].sum += (mid - s + 1) * tr[p].tag;
    tr[p * 2 + 1].sum += (t - mid) * tr[p].tag;
    tr[p * 2].sum %= mod;
    tr[p * 2 + 1].sum %= mod;
    tr[p * 2].tag += tr[p].tag;
    tr[p * 2 + 1].tag += tr[p].tag;
    tr[p * 2].tag %= mod;
    tr[p * 2 + 1].tag %= mod;
    tr[p].tag = 0;
}

void build(int l,int r, int p){
	if(l == r){
		tr[p].sum = segw[l];
		tr[p].sum %= mod;
		return;
	}
	int mid = (l + r) / 2;
	build(l,mid,p * 2);
	build(mid + 1,r,p * 2 + 1);
	pushup(p);
    return;
}

void segupd(int p, int s, int t, int l, int r,int x){
	if(t < l || s > r) return;
    if(l <= s && t <= r){
        tr[p].sum += (t - s + 1) * x;
        tr[p].tag += x;
        return;
    }
    int mid = (s + t) / 2;
    pushdown(p,s,t);
    segupd(p * 2, s, mid, l, r, x);
    segupd(p * 2 + 1, mid + 1, t, l, r, x);
    pushup(p);
    return;
}

int segq(int p, int s, int t, int l, int r){
    if(t < l || s > r) return 0;
    if(l <= s && t <= r){
        return tr[p].sum;
    }
    int mid = (s + t) / 2;
    pushdown(p,s,t);
    int ans = 0;
    ans += segq(p * 2, s, mid, l, r);
	ans += segq(p * 2 + 1, mid + 1, t, l, r);
    pushup(p);
	ans %= mod;
	return ans;
}

void dfs1(int x, int f){
	siz[x] = 1;
	fa[x] = f;
	dep[x] = dep[f] + 1;
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		if(v == f) continue;
		dfs1(v,x);
		siz[x]+=siz[v];
		if(siz[v]>siz[son[x]]){
			son[x]=v;
		}
	}
}

void dfs2(int x,int topf){
	top[x] = topf;
	dfn[x] = ++cnt;
	rev[cnt] = x;
	segw[cnt] = w[x];
	if(son[x]){
		dfs2(son[x],topf);
	}
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		if(v == fa[x] || v == son[x]) continue;
		dfs2(v,v);
	}
}

void updrange(int x, int y, int z){
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x,y);
		segupd(1,1,n,dfn[top[x]],dfn[x],z);
		x = fa[top[x]]; 
	}
	if(dep[x] < dep[y]) swap(x,y);
	segupd(1,1,n,dfn[y],dfn[x],z);
}

int qrange(int x, int y){
    long long ans = 0;
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x,y);
		ans += segq(1,1,n,dfn[top[x]],dfn[x]);
		ans %= mod;
		x = fa[top[x]]; 
	}
	if(dep[x] < dep[y]) swap(x,y);
	ans += segq(1,1,n,dfn[y],dfn[x]);
	ans %= mod;
	return ans;
}

void updtr(int x, int z){
	segupd(1,1,n,dfn[x],dfn[x] + siz[x] - 1,z);
}

int qtr(int x){
	return segq(1,1,n,dfn[x],dfn[x] + siz[x] - 1);
}

dinic

struct DINIC{

    int cur[N],dep[N];
    bool vis[N];
    queue<int> q;

    bool bfs(){
        for(int i = 0; i <= t; i ++){
            dep[i] = inf, cur[i] = head[i], vis[i] = 0;
        }
        q.push(s);
        dep[s] = 0;
        while(!q.empty()){
            int x = q.front();
            q.pop();
            vis[x] = 0;
            for(int i = head[x]; i; i = nxt[i]){
                int v = to[i];
                if(dep[v] > dep[x] + 1 && w[i]){
                    dep[v] = dep[x] + 1;
                    if(!vis[v]){
                        q.push(v);
                        vis[v] = 1;
                    }
                }
            }
        }
        if(dep[t] != inf) return 1;
        else return 0;
    }

    ll dfs(int x, ll flow){
        ll rlow = 0;
        if(x == t){
            maxflow += flow;
            return flow;
        }
        ll used = 0;
        for(int i = cur[x]; i; i = nxt[i])
        {
            int v = to[i];
            cur[x] = i;
            if(dep[v] == dep[x] + 1 && w[i]){
                if(rlow = dfs(v,min(flow - used,w[i]))){
                    used += rlow;
                    w[i] -= rlow;
                    w[i^1] += rlow;
                    if(used == flow) break;
                }
            }
        }
        return used;
    }

    ll dinic(){
        while(bfs()){
            dfs(s,inf);
        }
        return maxflow;
    }
}di;

isap

void bfs(){
	for(int i = 0; i <= n + 1; i++){
		dep[i] = -1;
		gap[i] = 0;
		cur[i] = head[i];
	}
	q.push(t);
	dep[t] = 0;
	gap[0] = 1;
	while(!q.empty()){
		int x = q.front();
		q.pop();
		for(int i = head[x]; i; i = nxt[i]){
			int v = to[i];
			if(dep[v] != -1) continue;
			dep[v] = dep[x] + 1;
			gap[dep[v]] ++;
			q.push(v);
		}
	}
}

ll dfs(int x,int flow){
	if(x == t){
		maxflow += flow;
		return flow;
	}
	ll used = 0;
	for(int i = cur[x]; i; i = nxt[i]){
		cur[x] = i;
		int v = to[i];
		if(dep[v] + 1 == dep[x] && w[i]){
			int rlow = dfs(v,min(flow - used, w[i]));
			if(rlow){
				w[i] -= rlow;
				w[i ^ 1] += rlow;
				used += rlow;
			}
			if(rlow == used) return used;
		}
	}
	gap[dep[x]] --;
	if(gap[dep[x]] == 0) dep[s] = n + 1;
	dep[x]++;
	gap[dep[x]] ++;
	return used;
}

ll isap(){
	maxflow = 0;
	bfs();
	while(dep[s] < n){
		memcpy(cur,head,sizeof(head));
		dfs(s,0x3ffffff);
	}
	return maxflow;
}

dinic费用流

bool spfa(){
	for(int i = 1; i <= n; i ++){
		vis[i] = 0, dep[i] = 0x3fffff; cur[i] = head[i];
	}
	q.push(s);
	dep[s] = 0;
	while(!q.empty()){
		int x = q.front();
		q.pop();
		// printf("x = %d\n",x);
		vis[x] = 0;
		for(int i = head[x]; i; i = nxt[i]){
			int v = to[i];
			// printf(" v = %d\n",v);
			if(dep[v] > dep[x] + c[i] && w[i]){
				dep[v] = dep[x] + c[i];
				// printf("  depv = %d\n",dep[v]);
				if(!vis[v]){
					// printf("v.inque\n");
					vis[v] = 1;
					q.push(v);
				}
			}
		}
	}
	if(dep[t] != 0x3fffff) return 1;
	else return 0;
}

ll dfs(int x,ll flow){
	if(x == t){
		vis[t] = 1;
		maxflow += flow;
		return flow;
	}
	ll used = 0;
	ll rlow = 0;
	vis[x] = 1;
	for(int i = head[x]; i; i = nxt[i]){
		// cur[x] = i;
		int v = to[i];
		if(dep[v] == dep[x] + c[i] && w[i] && (!vis[v] || v == t ) ){
			rlow = dfs(v, min(flow - used, w[i]));
			if(rlow != 0){
				cost += rlow * c[i];
				used += rlow;
				w[i] -= rlow;
				w[i ^ 1] += rlow;
			}
			if(used == flow){
				break;
			}
		}
	}
	return used;
}

ll dinic(){
	while(spfa()){
		vis[t] = 1;
		while(vis[t]){
			memset(vis,0,sizeof(vis));
			dfs(s,0x3fffffff);
		}
	}
	return maxflow;
}

如果两点之间边比较多,以防被卡可以用这个

struct DINIC{
    int dis[N], cur[N], dep[N];
    bool vis[N];

    bool spfa(){
        deque<int> q;
        for(int i = 0; i <= t; i ++) dis[i] = inf, cur[i] = head[i], vis[i] = 0, dep[i] = 0;
        q.push_front(s), dis[s] = 0;
        int len = 1, sum = 0;
        while(!q.empty()){
            int x = q.front(); q.pop_front();
            for(int i = head[x]; i; i = nxt[i]){
                int v = to[i];
                if(dis[v] > dis[x] + c[i] && w[i]){
                    dis[v] = dis[x] + c[i];
                    dep[v] = dep[x] + 1;
                    if(!vis[v]){
                        if(!q.empty() && dis[v] < dis[q.front()]) q.push_front(v);
                        else q.push_back(v);
                        vis[v] = 1;
                        len ++; sum += dis[v];
                    }
                }
            }
            vis[x] = 0;
        }
        return dis[t] != inf;
    }

    int dfs(int x, int flow){
        if(x == t){ maxflow += flow; return flow; }
        int rlow = 0, used = 0;
        vis[x] = 1;
        for(int i = cur[x]; i; i = nxt[i]){
            cur[x] = i;
            int v = to[i];
            if(dep[v] == dep[x] + 1 && dis[v] == dis[x] + c[i] && w[i] && (!vis[v]|| v == t) ){
                rlow = dfs(v, min(flow - used, w[i]));
                if(rlow){
                    cost += rlow * c[i];
                    w[i] -= rlow;
                    w[i ^ 1] += rlow;
                    used += rlow;
                    if(used == flow) break;
                }
            }
        }
        return used;
    }   


    int dinic(){
        while(spfa()){
            dfs(s, inf);
        }
        return maxflow;
    }
}di;

2sat

void tarjan(int x){
	dfn[x] = low[x] = ++dfn_clock;
	s.push(x);
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		if(!dfn[v]){
			tarjan(v);
			low[x] = min(low[x], low[v]);
		}
		else if(!sccnum[v]){
			low[x] = min(low[x], dfn[v]);
		}
	}
	if(low[x] == dfn[x]){
		++scccnt;
		while(1){
			int u = s.top();
			s.pop();
			sccnum[u] = scccnt;
			if(x == u) break;
		}
	}
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i = 1, x, a, y, b; i <= m ; i ++){
		scanf("%d%d%d%d",&x,&a,&y,&b);
		// printf("%d %d, %d %d\n", x + (n*(1-a)), y + (n*b), y + (n*(1-b)), x + (n*a));
		add(x + (n*(1-a)),y + (n*b) );
		add(y + (n*(1-b)),x + (n*a) );
	}
	for(int i =1; i <= 2*n; i ++) if(!dfn[i]) tarjan(i);
	for(int i = 1; i <= n ; i ++){
		if(sccnum[i] == sccnum[i + n] && sccnum[i] != 0){
			printf("IMPOSSIBLE");
			return 0;
		}
		else{
			if(sccnum[i] < sccnum[i + n]) ans[i] = 0;
			else ans[i] = 1;
		}
	}
	printf("POSSIBLE\n");
	for(int i = 1; i <= n ; i ++){
		printf("%d ",ans[i]);
	}
	return 0;
}

二分图最大匹配(dinic)

bool bfs(){
	for(int i = 0; i <= n + m + 1; i ++){
		dep[i] = 0x3ffffff, vis[i] = 0, cur[i] = head[i];
	}
	q.push(s);
	dep[s] = 0;
	while(!q.empty()){
		int x = q.front();
		q.pop();
		vis[x] = 0;
		for(int i = head[x]; i; i = nxt[i]){
			int v = to[i];
			if(dep[v] > dep[x] + 1 && w[i]){
				dep[v] = dep[x] + 1;
				if(!vis[v]){
					q.push(v);
					vis[v] = 1;
				}
			}
		}
	}
	if(dep[t] != 0x3ffffff) return 1;
	else return 0;
}

ll dfs(int x, int flow){
	if(x == t){
		maxflow += flow;
		return flow;
	}
	ll used = 0;
	ll rlow = 0;
	for(int i = cur[x]; i; i = nxt[i]){
		cur[x] = i;
		int v = to[i];
		if(dep[v] == dep[x] + 1 && w[i]){
			if(rlow = dfs(v,min(flow - used, w[i]))){
				used += rlow;
				w[i] -= rlow;
				w[i ^ 1] += rlow;
				if(used == flow) break;
			}
		}
	}
	return used;
}

ll dinic(){
	while(bfs()){
		dfs(s,0x3ffffff);
	}
	return maxflow;
}

匈牙利算法

bool fd(int u){
	for(int i = head[u]; i ;i = nxt[i]){
		int v = to[i];
		if(!vis[v]){
			vis[v] = 1;
			if(!cy[v] || fd(cy[v])){
				cy[v] = u;
				return true;
			}
		}
	}
	return false;
}

for(int i = 1; i <= n ; i ++){
	memset(vis,0,sizeof(vis));
	if(fd(i)) ans ++;
}

点分治

void getrt(int x, int fa){
	sz[x] = 1;
	mx[x] = 0;
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		if(vis[v] || v == fa) continue;
		getrt(v,x);
		sz[x] += sz[v];
		mx[x] = max(mx[x],sz[v]);
	}
	mx[x] = max(mx[x], s - sz[x]);
	if(mx[x] < mx[rt]){
		rt = x;
	}
}

void getdis(int u, int fa){
	d[++tot] = dis[u];
	for(int i = head[u]; i; i = nxt[i]){
		int v = to[i];
		if(vis[v] || v == fa) continue;
		dis[v] = dis[u] + w[i];
		getdis(v,u);
	}
}

void calc(int x){
	qwq = 0; t[0] = 1;
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		if(vis[v]) continue;
		dis[v] = w[i], tot = 0, getdis(v,x);
		for(int u = 1; u <= tot; u ++){
			for(int k = 1; k <= m ; k ++){
				if(q[k] >= d[u] && t[q[k] - d[u]]) ans[k] = 1;
			}
		}
		for(int u = 1; u <= tot; u ++) if(d[u] <= 1e7) t[d[u]] = 1,  tsh[++qwq] = d[u];
	}
	while(qwq) t[tsh[qwq--]] = 0;
}

void solve(int x){
	vis[x] = 1, calc(x);
	for(int i = head[x]; i; i = nxt[i]){
		int v = to[i];
		if(vis[v]) continue;
		getrt(v,x);
		s = sz[v], rt = 0, mx[0] = 1e9;
		getrt(v,x);
		solve(rt);
		// printf("x = %d\n",x);
		// tie();
	}
}

数据结构

树状数组


int lowbit(int x){
	return x & (-x);
}

void add(int x, int y){
	for(int i = x; i <= n; i += lowbit(i)){
		c1[i] += y;
		c2[i] += y * x;
	}
}

int query(int x){
	int res = 0;
	for(int i = x; i ; i -= lowbit(i)){
		res += c1[i] * (x + 1) - c2[i];
	}
	return res;
}

  ans = query(r) - query(l));
			

二维树状数组

int lowbit(int x){
	return x & (-x);
}

void add(int x,int y, int z){
	for(int i = x; i <= n ; i += lowbit(i)){
		for(int u = y; u <= m; u += lowbit(u)){
			c1[i][u] += z;
			c2[i][u] += z * x;
			c3[i][u] += z * y;
			c4[i][u] += z * x * y;
		}
	}
}

int query(int x, int y){
	int res = 0;
	for(int i = x; i; i -= lowbit(i)){
		for(int u = y;u; u -= lowbit(u)){
			res += (x + 1)*(y + 1)*c1[i][u] - (y + 1)*c2[i][u] - (x + 1)*c3[i][u] + c4[i][u];
		}
	}
	return res;
}

ans = query(a - 1,b - 1) + query(c,d) - query(a - 1,d) - query(c,b - 1);

单调队列

//n为数据个数,m为窗口长度; 
for(int i = 1; i <= n; i ++){
	if(q[head] <= i - m) head ++;
	while(head <= tail && a[q[tail]] < a[i]) tail --;
	q[++tail] = i;
	ans[i] = a[q[head]];
}
for(int i = m ; i <= n ; i ++){
	//对每个窗口中已选出的数据进行处理 ; 
}

线段树

struct SEG{
	#define mid ((s + t) >> 1)
	#define ls p<<1
	#define rs p<<1|1
	#define lson p<<1,s,mid
	#define rson p<<1|1,mid+1,t
    int sum[N<<2], tag[N<<2];

    void pushup(int p){sum[p] = sum[ls] + sum[rs];}

    void pushdown(int p,int s,int t){
        tag[ls] += tag[p]; 
        tag[rs] += tag[p];
        sum[ls] += tag[p] * (mid - s + 1);
        sum[rs] += tag[p] * (t - mid);
        tag[p] = 0;
    }

    void build(int p, int s, int t){
        if(s == t){sum[p] = a[s]; return;}
        build(lson); build(rson); pushup(p);
    }

    void upd(int p, int s, int t, int l, int r, int x){
        if(t < l || s > r) return;
        if(l <= s && t <= r){sum[p] += (t - s + 1) * x, tag[p] += x; return;}
        pushdown(p,s,t);
        upd(lson,l,r,x); upd(rson,l,r,x);
        pushup(p);
    }

    int query(int p, int s, int t, int l, int r){
        if(t < l || s > r) return 0;
        if(l <= s && t <= r) return sum[p];
        pushdown(p,s,t);
        return query(lson,l,r) + query(rson,l,r);
    }
}seg;

ST表

void pre() {
    logn[1] = 0;
    logn[2] = 1;
    for (int i = 3; i <= N - 1; i++) { //注意这里一定是N - 1 绝对不能是N
        logn[i] = logn[i / 2] + 1;
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &st[i][0]);
    pre();
    for (int u = 1; u <= 20; u++) {
        for (int i = 1; i + (1 << u) - 1 <= n; i++) {
            st[i][u] = max(st[i][u - 1], st[i + (1 << (u - 1))][u - 1]);
        }
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &l, &r);
        int k = logn[r - l + 1];
        printf("%d\n", max(st[l][k], st[r - (1 << k) + 1][k]));
    }
    return 0;
}

二维st表

scanf("%d%d%d",&n,&m,&k1);
	for(int i = 1; i <= n ; i ++){
		for(int u = 1; u <= m; u ++){
			scanf("%d",&st[i][0][u][0]);
		}
	}
	logn[1] = 0;
	logn[2] = 1;
	for(int i = 3; i <= N - 1; i ++){
		logn[i] = logn[i / 2] + 1;
	}
	
	for(int k = 0; k <= 20; k ++){
		for(int h = 0; h <= 20; h ++){
			if(!k && !h) continue;
			for(int i = 1; i + (1 << k) - 1 <= n; i ++){
				for(int u = 1; u + (1 << h) - 1 <= m; u ++){
					if(k) st[i][k][u][h] = max(st[i][k - 1][u][h],st[i + (1 << (k - 1))][k - 1][u][h]);
					else st[i][k][u][h] = max(st[i][k][u][h - 1],st[i][k][u + (1 << (h - 1))][h - 1]);
//					st[i][k][u][h] = max({st[i][k - 1][u][h - 1], 
//										 st[i + (1 << (k - 1))][k - 1][u][h - 1],  
//										 st[i][k - 1][u + (1 << (h - 1))][h - 1],  
//										 st[i + (1 << (k - 1))][k - 1][u + (1 << (h - 1))][h - 1]});
				}
			}
		}
	}
	for(int i = 1,x1,y1,x2,y2; i <= k1; i ++){
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		int k1 = logn[x2 - x1 + 1];
		int k2 = logn[y2 - y1 + 1];
		printf("%d\n",max({st[x1][k1][y1][k2],
						  st[x2 - (1 << k1) + 1][k1][y1][k2],
						  st[x1][k1][y2 - (1 << k2) + 1][k2],
						  st[x2 - (1 << k1) + 1][k1][y2 - (1 << k2) + 1][k2]}));
	}

分块

scanf("%lld%lld",&n,&m);
	for(int i = 1; i <= n ; i ++){
		scanf("%lld",&a[i]);
		sum1[i] = sum1[i - 1] + a[i];
	}
	k = sqrt(n);
	for(int i = 1; i <= n / k + 1 ; i ++){
		for(int u = 1; u <= k && u <= n; u ++){
			pos[u + (i - 1) * k] = i;
			if(!pl[i])pl[i] = u + i * k - k;
			pr[i] = min(u + i * k - k,n);
		}
		sum[i] = sum1[pr[i]] - sum1[pl[i] - 1];
	}
for(int u = 1; u <= m ; u ++){
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt == 1){
			scanf("%lld",&c);
			if(pos[r] - pos[l] > 1){
				int l1 = pos[l] + 1;
				while(l1 < pos[r]) tag[l1] += c,l1 ++;
				for(int i = l; i <= pr[pos[l]]; i ++) a[i] += c,sum[pos[i]] += c;//printf("%d %d\n",i,a[i]);
				for(int i = r; i >= pl[pos[r]]; i --) a[i] += c,sum[pos[i]] += c;//printf("%d %d\n",i,a[i]);
			}
			else for(int i = l; i <= r; i ++) a[i] += c,sum[pos[i]] += c;
		}
else{
			ans = 0;
			if(pos[r] - pos[l] > 1){
				int l1 = pos[l] + 1;
				while(l1 < pos[r]){
					ans = ans + sum[l1] + tag[l1] * (pr[l1] - pl[l1] + 1), l1++;
				}
				for(int i = l; i <= pr[pos[l]]; i ++) ans += a[i] + tag[pos[i]];//printf("%d %d\n",i,ans);
				for(int i = r; i >= pl[pos[r]]; i --) ans += a[i] + tag[pos[i]];//printf("%d %d\n",i,ans);
			}
			else for(int i = l; i <= r; i ++) ans += a[i] + tag[pos[i]] ;
			printf("%lld\n",ans);
		}

左偏树

int find(int x){
	return f(x) == x ? x : f(x) = find(f(x));
}

int merge(int x,int y){
	if(!x || !y) return x + y ;
	if(v(x) < v(y)) swap(x,y);
	dp[x] += dp[y];
	sz[x] += sz[y];
	rs(x) = merge(rs(x),y);
	if(d(ls(x)) < d(rs(x))) swap(ls(x),rs(x));
	d(x) = d(rs(x)) + 1;
	f(x) = f(rs(x)) = f(ls(x)) = x;
	return x;
}

int pop(int x){
	return merge(ls(x),rs(x));
}

Splay

struct SPLAY{
	int son[N][2], cnt[N] ,sz[N], fa[N] , val[N];
	int rt = 0, tot = 0;

	int newnode(int x, int f){
		val[++tot] = x;
		fa[tot] = f;
		son[tot][0] = son[tot][1] = 0;
		cnt[tot] = sz[tot] = 1;
		return tot;
	}

	void maintain(int x){
		sz[x] = cnt[x] + sz[son[x][0]] + sz[son[x][1]];
	}

	bool getf(int x){
		return x == son[fa[x]][1];
	}

	void rotate(int x){
		int f = fa[x]; int gf = fa[f];
		bool i = getf(x), u = getf(f);
		son[f][i] = son[x][i ^ 1];
		fa[son[x][i ^ 1]] = f;
		son[x][i ^ 1] = f;
		fa[f] = x, fa[x] = gf;
		if(gf) son[gf][u] = x;
		maintain(x);
		maintain(f);
		//
	}

	void splay(int x){
		for(int f = fa[x]; f = fa[x]; rotate(x)){
			if(fa[f]){
				if(getf(f) == getf(x)) rotate(f);
				else rotate(x);
			}
		}
		rt = x;
	}

	void insert(int x){
		if(rt == 0){
			rt = newnode(x,0);
			// printf(" rt = %d\n",rt);
			return;
		}
		int now = rt, f = 0;
		while(1){
			if(val[now] == x){
				cnt[now] ++;
				maintain(now);
				maintain(f);
				splay(now);
				return;
			}
			f = now;
			now = son[f][x > val[f]];
			if(!now){
				now = newnode(x,f);
				son[f][x > val[f]] = now;
				// printf("  1 : f = %d, valf = %d, now = %d, son = %d\n",f,val[f], now,getf(now));
				maintain(f);
				splay(now);
				// printf("  2 : rt = %d, val = %d, lson = %d, rson = %d\n",rt,val[rt],son[rt][0], son[rt][1]);
				return;
			}
		}
	}

	int kth(int x){
		int now = rt;
		while(1){
			if(sz[son[now][0]] >= x) now = son[now][0];
			else if(sz[son[now][0]] + cnt[now] >= x) return val[now];
			else{
				x -= (sz[son[now][0]] + cnt[now]);
				now = son[now][1];
			}
		}
	}

	int rank(int x){
		int now = rt, ans = 0;
		while(1){
			if(!now) return ans + 1;
			if(val[now] > x) now = son[now][0];
			else if(val[now] == x){
				ans += sz[son[now][0]];
				splay(now);
				return ans + 1;
			}
			else{
				ans += cnt[now] + sz[son[now][0]];
				now = son[now][1];
			}
		}
	}

	int findpre(){
		int now = son[rt][0];
		// printf("%d %d\n",rt,now);
		while(son[now][1]) now = son[now][1];
		return now;
	}

	int findnxt(){
		int now = son[rt][1];
		while(son[now][0]) now = son[now][0];
		return now;
	}

	void del(int x){
		int ss = rank(x);
		// printf("rank = %d\n",rank(x));
		if(cnt[rt] > 1) cnt[rt] --;
		else{
			if(!son[rt][1] && !son[rt][0]) rt = 0;
			else if(!son[rt][0]) rt = son[rt][1], fa[rt] = 0;
			else if(!son[rt][1]) rt = son[rt][0], fa[rt] = 0;
			else{
				int rs = son[rt][1];
				int pre = findpre();
				splay(pre);
				son[pre][1] = rs;
				fa[rs] = pre;
				maintain(pre);
			}
		}
	}

	void tri(int x){
		if(son[x][0]) tri(son[x][0]);
		// printf(" %d %d\n",x,val[x]);
		if(son[x][1]) tri(son[x][1]);
	}
}splay;

FHQ

struct FHQTREAP{
    int ls[N], rs[N], val[N], pri[N], sz[N];
    int tot = 0, rt = 0;

    void newnode(int x){
        tot ++;
        ls[tot] = rs[tot] = 0;
        val[tot] = x, pri[tot] = rand();
        sz[tot] = 1;
    }

    void upd(int x){
        sz[x] = sz[ls[x]] + sz[rs[x]] + 1;
    }

    void split( int u,int x, int &l, int &r){
        if(u == 0){
            l = 0, r = 0;
            return;
        }
        if(val[u] <= x){
            l = u;
            split(rs[u],x,rs[u],r);
        }
        else{
            r = u;
            split(ls[u],x,l,ls[u]);
        }
        upd(u);
        return;
    }

    int merge(int l, int r){
        if(!l || !r) return l + r;
        if(pri[l] > pri[r]){
            rs[l] = merge(rs[l],r);
            upd(l);
            return l;
        }
        else{
            ls[r] = merge(l,ls[r]);
            upd(r);
            return r;
        }
    }

    int insert(int x){
        int l, r;
        split(rt,x,l,r);
        newnode(x);
        rt = merge(merge(l,tot),r);
        return tot;
    }

    void del(int x){
        int l, r, m;
        split(rt,x, l, r);
        split(l,x - 1, l, m);
        m = merge(ls[m], rs[m]);
        rt = merge(merge(l,m),r);
    }

    int rank(int x){
        int l, r;
        split(rt,x - 1,l,r);
        int res = sz[l] + 1;
        rt = merge(l,r);
        return res;
    }

    int kth(int u, int x){
        // printf(" %d %d %d %d\n",u,ls[u],sz[ls[u]],x);
        if(sz[ls[u]] + 1 == x) return u;
        else if(sz[ls[u]] >= x) return kth(ls[u],x);
        else return kth(rs[u], x - sz[ls[u]] - 1);
    }

    int pre(int x){
        int l, r;
        split(rt,x - 1, l, r);
        int res = val[kth(l,sz[l])];
        merge(l,r);
        return res;
    }

    int nxt(int x){
        int l, r;
        split(rt,x,l,r);
        int res = val[kth(r,1)];
        merge(l,r);
        return res;
    }
}fhq;

数论

快速幂

注意:不开ll会炸

long long quickpow(long long a, long long b, long long n){
	long long res = 1;
	while(b){
		if(b % 2 == 1) res = res * a % n;
		a = a * a % n;
		b /= 2;
	}
	return res % n;
}

矩阵快速幂

const int mod = 1e9 + 7;
const int lim = ;
long long n;

struct mat{
	ll m[lim + 2][lim + 2];
};
mat f, ans, t, f1;

void matinit(mat &x){
	for(int i = 1; i <= lim; i ++){
		for(int u = 1; u <= lim; u ++){
			if(i == u) x.m[i][u] = 1ll;
			else x.m[i][u] = 0ll;
		}
	}
}

mat matmul(mat x, mat y){
	mat z;
	memset(z.m,0,sizeof(z.m));
	for(int i = 1; i <= lim ; i ++){
		for(int k = 1; k <= lim; k ++){
			if(x.m[i][k]){
				for(int u = 1; u <= lim; u ++){
					z.m[i][u] += x.m[i][k] % mod * y.m[k][u] % mod;
					z.m[i][u] %= mod;
				}
			}
		}
	}
	return z;
}

mat matquickpow(mat a, long long b){
	mat res;
	matinit(res);
	while(b){
		if(b & 1) res = matmul(res,a);
		a = matmul(a,a);
		b >>= 1;
	}
	return res;
}

欧拉筛

void getprime(){
	for(int i = 2; i <= n ; i ++){
		if(pflag[i] == false)	pri[++top] = i;
		for(int q = 1; pri[q] * i <= n ; q ++){
			pflag[pri[q] * i] = true;
			if(i % pri[q] == 0) break;
		}
	}
}

算术基本定理

for(int i = 2; i * i <= A ; i ++){
		if(A % i != 0) continue;
		int num = 0;
		while(A % i == 0){
			A /= i;
			num ++;
		}
		printf("%d %d\n",i,num);
		work(i,B * num + 1);
	}
	if(A > 1) printf("%d %d",A,1);

exgcd

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

lucas定理

ll C(ll n, ll m,ll mod){
	if(m > n) return 0;
	return jie[n] * qpow(jie[m],mod - 2, mod) % mod * qpow(jie[n - m],mod - 2, mod) % mod;
}

ll lucas(ll n, ll m,ll mod){
	if(m == 0) return 1;
	return C(n % mod, m % mod,mod) * lucas(n / mod, m / mod,mod) % mod;
}

中国剩余定理

ll crt(){
	ll ans = 0;
	for(int i = 1; i <= 4; i ++){
		ll x, y; exgcd(mod / b[i],b[i],x,y);
		x = (x  + b[i]) % b[i];
		a[i] = (a[i] + b[i]) % b[i];
		ans = (ans + qmul(mod / b[i] * x, a[i])) % mod;
	}
	return ans % mod;
}

线性求逆元

inv[1] = 1;
    for (int i = 2; i <= n; i++) {
        inv[i] = (p - p / i) * inv[p % i];
        inv[i] %= p;
    }

求一个数的欧拉函数

int phi(int n){
    int ans=n,num=1;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i)continue;
        ans=ans/i*(i-1);
        while(!(n%i))n/=i;
    }
    if(n^1) ans=ans/n*(n-1);
    return ans;
}

线性筛欧拉函数

void init(int n){
    phi[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i])p[++cnt]=i,phi[i]=i-1;
        for(int j=1;j<=cnt&&i*p[j]<=n;j++){
            vis[i*p[j]]=1;
            if(!(i%p[j])){
                phi[i*p[j]]=phi[i]*p[j];
                break;
            }
            phi[i*p[j]]=phi[i]*phi[p[j]];
        }
    }
}

线性筛莫比乌斯函数

void getmul(){
	mu[1] = 1;
	// int mn = min(m,n);
	for(int i = 2; i <= N - 1 ; i ++){
		if(!np[i]) pri[++tot] = i, mu[i] = -1;
		for(int u = 1; u <= tot && pri[u] * i <= N - 1; u ++){
			np[pri[u] * i] = 1;
			mu[pri[u] * i] = -1 * mu[i];
			if(i % pri[u] == 0){
				mu[pri[u] * i] = 0;
				break;
			}
		}
	}
}

莫比乌斯反演

int ans = 0;
int r = 0;
for(int i = 1; i <= min(n, m); i = r + 1){
	r = min(n / (n / i), m / (m / i));
	ans += (s[r] - s[i - 1]) * (n / i) * (m / i);
}

字符串

哈希(习惯性采用双哈希)

for (int i = 1; i <= n; i++) {
    cin >> s;
    unsigned long long t1 = 0, t2 = 0;
    for (int u = 0; u < s.size(); u++) {
        t1 = s[u] * p1 + t1 * p1;
        t2 = s[u] * p2 + t2 * p2;
    }
    hash1[i] = t1 + t2;
}

KMP

void kmp1(){
	int j = 0;
	for(int i = 2; i <= lb; i ++){
		if(j&& b[i] != b[j + 1]) j = kmp[j];
		if(b[i] == b[j + 1]) j ++;
		kmp[i] = j;
	}
	j = 0;
	for(int i = 1; i <= la; i ++){
		while(j && a[i] != b[j + 1]) j = kmp[j];
		if(a[i] == b[j + 1]) j ++;
		if(j == lb){
			cnt ++;
			j = kmp[j];
		}
	}
}

trie树

void triein(string s) {
    int l = s.size();
    int p = 0;
    for (int i = 0; i < l; i++) {
        int c = s[i] - 'a';
        if (!nex[p][c])
            nex[p][c] = ++cnt;
        p = nex[p][c];
        //		printf("1 %d %d %d\n",i,c,nex[p][c]);
    }
    ++exist[p];
}

int triequery(string s) {
    int l = s.size();
    int p = 0;
    int tot = 0;
    for (int i = 0; i < l; i++) {
        int c = s[i] - 'a';
        p = nex[p][c];
        //执行操作
    }
    return tot;
}

AC自动机

struct trie {
    int fail, exist, nex[27];
    bool vis;
};
trie tr[N];

void build(string s) {
    int p = 0;
    int l = s.size();
    for (int i = 0; i < l; i++) {
        int c = s[i] - 'a';
        if (!tr[p].nex[c])
            tr[p].nex[c] = ++cnt;
        p = tr[p].nex[c];
    }
    tr[p].exist++;
}

void getfail() {
    queue<int> q;
    for (int i = 0; i < 26; i++)
        if (tr[0].nex[i])
            q.push(tr[0].nex[i]);
    //	for(int i = 0; i < )
    while (!q.empty()) {
        int now = q.front();
        q.pop();
        //		printf("now = %d\n",now);
        for (int i = 0; i < 26; i++) {
            if (!tr[now].nex[i])
                tr[now].nex[i] = tr[tr[now].fail].nex[i];
            else
                tr[tr[now].nex[i]].fail = tr[tr[now].fail].nex[i], q.push(tr[now].nex[i]);
        }
    }
}

int AC(string s) {
    int l = s.size();
    int res = 0;
    int p = 0;
    for (int i = 0; i < l; i++) {
        int c = s[i] - 'a';
        p = tr[p].nex[c];
        for (int u = p; tr[u].exist != -1; u = tr[u].fail) {
            res += tr[u].exist;
            tr[u].exist = -1;
        }
    }
    return res;
}

Manacher

char ms[N];
int l, mana[N], c = -1, r = -1, ans = -10;

int main(){
	cin>>s;
	for(int i = 1; i <= s.size(); i ++){
		ms[i * 2 - 2] = '@';
		ms[i * 2 - 1] = s[i - 1];
	}
	ms[s.size() * 2] = '@';
	l = s.size()* 2;
	for(int i = 0; i <= l; i ++){
		if(i > r){
			int pr = i;
			while(ms[pr] == ms[i * 2 - pr] && i * 2 - pr >= 0){
				mana[i] ++;
				pr ++;
			}
		}
		else{
			int i1 = c * 2 - i;
			int l1 = c * 2 - r;
			if(i1 - mana[i1] + 1 > l1){
				mana[i] = mana[i1];
			}
			else{
				mana[i] = i1 - l1 + 1;
				int r1 = r + 1;
				while(ms[r1] == ms[i * 2 - r1] && i * 2 - r1 >= 0){
					mana[i] ++;
					r1 ++;
				}
			}
		}
		if(i + mana[i] - 1 > r) r = i + mana[i] - 1, c = i;
	}
	for(int i = 0; i <= l; i ++){
		ans = max(ans, mana[i] - 1);
	}

杂项

cdq分治

struct node {
    int a, b, c, cnt, ans;
    friend bool operator==(node e, node f) { return e.a == f.a && e.b == f.b && e.c == f.c; }
};
node e[N], tmp[N];

bool cmp(node e, node f) {
    if (e.a != f.a)
        return e.a < f.a;
    else if (e.b != f.b)
        return e.b < f.b;
    else
        return e.c < f.c;
}

bool cmp2(node e, node f) {
    if (e.b != f.b)
        return e.b < f.b;
    else if (e.c != f.c)
        return e.c < f.c;
    else
        return e.a < f.a;
}

struct BMP {
    int c[M];

    int lowbit(int x) { return x & (-x); }

    void add(int x, int y) {
        for (int i = x; i <= k; i += lowbit(i)) c[i] += y;
    }

    int query(int x) {
        int res = 0;
        for (int i = x; i; i -= lowbit(i)) res += c[i];
        return res;
    }
} bmp;

void cdq(int l, int r) {
    if (l == r)
        return;
    int mid = (l + r) / 2;
    cdq(l, mid), cdq(mid + 1, r);
    sort(e + l, e + mid + 1, cmp2);
    sort(e + mid + 1, e + r + 1, cmp2);
    int s = l, t = mid + 1;
    while (t <= r) {
        if (s > mid)
            break;
        while (s <= mid && e[s].b <= e[t].b) {
            bmp.add(e[s].c, e[s].cnt);
            s++;
        }
        e[t].ans += bmp.query(e[t].c);
        t++;
    }
    // printf("%d %d %d %d %d\n",l,r,mid,s,t);
    for (int i = t; i <= r; i++) e[i].ans += bmp.query(e[i].c);
    // printf(" ans : "); for(int i = l; i <= r; i ++) printf("%d ",e[i].ans); printf("\n");
    // printf(" e1 : "); for(int i = l; i <= r; i ++) printf("%d ",bmp.query(e[i].c)); printf("\n");
    for (int i = l; i < s; i++) bmp.add(e[i].c, -1 * e[i].cnt);
    // printf(" e2 : "); for(int i = l; i <= r; i ++) printf("%d ",bmp.query(e[i].c)); printf("\n");
    return;
}

int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &tmp[i].a, &tmp[i].b, &tmp[i].c);
    }
    int m = 0;
    sort(tmp + 1, tmp + 1 + n, cmp);
    for (int i = 1; i <= n; i++) {
        int tot = 1;
        while (tmp[i] == tmp[i + 1]) {
            i++, tot++;
        }
        e[++m] = tmp[i];
        e[m].cnt = tot;
    }
    // printf("\n");
    // for(int i = 1; i <= n ; i ++) printf("%d %d %d %d\n",e[i].a,e[i].b, e[i].c, e[i].cnt);
    cdq(1, m);
    for (int i = 1; i <= m; i++) {
        res[e[i].ans + e[i].cnt - 1] += e[i].cnt;
    }
    for (int i = 0; i < n; i++) printf("%d\n", res[i]);
    return 0;
}
posted @ 2024-05-10 11:22  Nihachu  阅读(60)  评论(0编辑  收藏  举报