zoukankan      html  css  js  c++  java
  • 模板整合计划 写了一点qwq慢慢补

    板子整合计划

    求查错(qwq)
    不开(long~long)爆的连裤衩都没了

    inline int read(){//快读 cctype iostream
    	int x = 0; bool op = 0;char c = getchar();
    	while(!isdigit(c))op |= (c == '-'), c = getchar();
    	while(isdigit(c))x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return op ? -x : x;
    }
    inline int read(){
    	int x = 0; bool op = 0;char c = getchar();
    	while(c > '9' || c < '0')op |= (c == '-'), c = getchar();
    	while(c>='0'&&c<='9')x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    	return op ? -x : x;
    }
    

    找树的直径 两遍(dfs)写法

    dep[N] = {-1};
    void dfs(int x,int fa){
        dep[x] = dep[fa] + 1;
        if(dep[x] > dep[maxx]) maxx = x;//获取最深节点
        for(int i = head[x];i;i = e[i].next){
            int v = e[i].to; if(v == fa) continue;
            dfs(v,x);
        }
    }
    main(){
        dfs(1,0); dfs(maxx,0);
        cout<<dep[maxx];
    }
    

    换根dp

    void dp(int x){
        vis[x] = 1;
        for(int i = head[x];i;i = e[i].next){
            int v = e[i].to;
            if(vis[v]) continue; dp(y);
            ans = max(ans,dep[x]+dep[y]+e[i].w);
            dep[x] = max(dep[x],d[y] + e[i].w);
        }
    }
    

    kruskal最小生成树(最大把小于换大于)

    struct edge_tu{int from,to,w;}e1[N<<1];
    struct edge_tree{int from,to,w;}e2[N<<1];
    void add(int u,int v,int w){
        e2[++tot] = (edge_tree){head[u],v,w}; head[u] = tot;
    }
    int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
    bool cmp(edge_tu a,edge_tu b){
        return a.w < b.w;
    }
    void kruskal(){
        sort(e1 + 1,e1 + m + 1,cmp);
        for(int i = 1;i <= m;++i){
        	int x = find(e1[i].x),y = find(e1[i]); 
            if(x == y) continue; fa[x] = y;
            add(e1[i].u.e1[i].v,e1[i].w);
            add(e1[i].v, e1[i].u, e1[i].w);
            if (++num == n) return;
        }
    }
    

    快速幂龟速乘

    int qpow(int a,int b){
    	int ans = 1;
    	for(;b;b >>= 1){
    		if(b & 1) ans = (long long)ans * a % mod;
    		a = a * a % mod;
    	}
    	return ans;
    }
    ll mul(ll a,ll b){
    	ll ans = 0;
    	for(;b;b >>= 1){
    		if(b & 1) ans = (ans + a) % mod;
    		a = (a + a) % mod;
    	}
    	return ans;
    }
    

    (a*b~mod~p=a*b-lfloor a*b/p floor*p)

    线段树 单点修改 区间乘 区间加 区间和

    struct node{int v,add,mul;}tree[N<<2];
    void pushdown(int root,int l,int r){//维护lazy 
    	int mid = (l + r)>>1;//儿子的值*爸爸的mul+儿子的区间长度*爸爸的add 先求和,再lazy 
    	tree[root<<1].v = (tree[root<<1].v * tree[root].mul + tree[root].add * (mid - l + 1))%p;
    	tree[root<<1|1].v = (tree[root<<1|1].v*tree[root].mul+tree[root].add*(r - mid))%p;
    	tree[root<<1].mul = (tree[root].mul * tree[root<<1].mul)%p;
    	tree[root<<1|1].mul = (tree[root].mul * tree[root<<1|1].mul)%p;
    	tree[root<<1].add = (tree[root].mul * tree[root<<1].add + tree[root].add)%p;
    	tree[root<<1|1].add = (tree[root].mul * tree[root<<1|1].add + tree[root].add)%p;
    	tree[root].mul = 1; tree[root].add = 0; return;
    }
    void change(int root,int l,int r,int x,int data){
    	if(l == r) {
    		tree[root].v = data; 
    		tree[root].add = 0; tree[root].mul = 1; return;
    	}
    	pushdown(root,l,r);
    	int mid = (l + r) >>1;
    	if(x <= mid) change(root<<1,l,mid,x,data);
    	else change(root<<1|1,mid+1,r,x,data);
    	tree[root].v = (tree[root<<1].v + tree[root<<1|1].v) % p;
    }
    void build(int root,int l,int r){
    	tree[root].mul = 1;
    	tree[root].add = 0;
    	if(l == r) tree[root].v = a[l];//
    	else{
    		int mid = (l + r)>>1;
    		build(root<<1,l,mid); build(root<<1|1,mid +1,r);
    		tree[root].v = tree[root<<1].v + tree[root<<1|1].v;
    	}
    	tree[root].v %= p;
    	return;
    }
    void tmul(int root,int stdl,int stdr,int l,int r,int k){
    	if(r < stdl || l > stdr) return;
    	if(l <= stdl && r >= stdr){
    		tree[root].v = (tree[root].v * k) % p;
    		tree[root].mul = (tree[root].mul * k) % p;
    		tree[root].add = (tree[root].add * k) % p;
    		return;
    	}
    	pushdown(root,stdl,stdr);
    	int mid = stdl + stdr >>1;
    	tmul(root<<1,stdl,mid,l,r,k); tmul(root<<1|1,mid+1,stdr,l,r,k);
    	tree[root].v = (tree[root<<1].v + tree[root<<1|1].v) % p;
    	return;
    }
    void tadd(int root,int stdl,int stdr,int l,int r,int k){
    	if(r < stdl || l > stdr) return;
    	if(l <= stdl && r >= stdr){
    		tree[root].add = (tree[root].add + k) % p;
    		tree[root].v = (tree[root].v + k * (stdr - stdl + 1)) % p;
    		return;
    	}
    	pushdown(root,stdl,stdr);
    	int mid = stdl + stdr >> 1;
    	tadd(root<<1,stdl,mid,l,r,k); tadd(root<<1|1,mid+1,stdr,l,r,k);
    	tree[root].v = (tree[root<<1|1].v + tree[root<<1].v) % p;
    	return;
    }
    int query(int root,int stdl,int stdr,int l,int r){
    	if(r < stdl || l > stdr) return 0;
    	if(l <= stdl && r >= stdr) return tree[root].v;
    	pushdown(root,stdl,stdr);
    	int mid = (stdl + stdr) >> 1;
    	return (query(root<<1,stdl,mid,l,r) + query(root<<1|1,mid+1,stdr,l,r)) % p;
    }
    

    树状数组 单点+ 区间查询 逆序对 区间修改

    inline int lowbit(int x){return x & (-x);}
    inline void add(int a,int b){
    	for(;a <= n;a += lowbit(a)) c[a] += b;
    }
    inline int ask(int i){
    	int ans = 0;
    	for(;i;i -= lowbit(i)) ans += c[i];
    	return ans;
    }
    //逆序对
    for(int i = n;i;--i){
        ans += ask(a[i]-1);
        add(a[i],1);
    }
    //区间修改
    inline int query(int x){
    		int ans = 0;
    		for(int i = x;i;i -= lowbit(i))
    		ans += (x + 1) * c1[i] - c2[i];
    		return ans;
    	}
    	inline void add(int x,int a){
    		for(int i = x;i <= n;i += lowbit(i)) c1[i] += a,c2[i] += x * a;
    	}
    main:
    add(i,a[i]-a[i-1]);
    

    (RMQ - ST)

    (f[i][j])表示从(a[i])(a[i+2^j-1])的最大值/最小值

    (f[i][j])分成(f[i][j-1])(f[i+2^{j-1}][j-1])

    (f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]))

    边界(f[i][0]=a[i])

    log[0] = -1;
    for(int i = 1;i <= n;++i) log[i] = log[i>>1] + 1;
    for(int j = 1;j <= 20;++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]);
    //求区间[x,y]最大值
    int k = log[y-x+1];
    ans = max(f[x][k],f[y-(1<<k)+1][k])
    

    离散化

    memcpy(a,c,sizeof(c));
    sort(a + 1,a + n + 1);
    int siz = unique(a + 1,a + n + 1)- a - 1;
    for(int i = 1;i <= n;++i) b[i] = lower_bound(a + 1,a + siz + 1,a[i])-a+1;
    

    归并排序求逆序对

    inline void q_merge(int l, int r) {
    	if (l == r) return;
    	int mid = l + r >> 1;
    	q_merge(l, mid);
    	q_merge(mid + 1, r);
    	int i = l, j = mid + 1, k = l;
    	while(i <= mid || j <= r) {
    		if (j > r || i <= mid && a[i] <= a[j]) b[k ++] = a[i ++];
    		else {
    			b[k ++] = a[j ++];
    			ans += mid - i + 1;
    		} 
    	}
    	for (int i = l; i <= r; i ++) a[i] = b[i];
    	return;
    }
    

    tarjan找割边 (dfn[x]<low[y])

    //tarjan找割边/桥
    void tarjan(int x,int in_edge){
    	dfn[x] = low[x] = ++num;
    	for(int i = head[x];i;i = e[i].next){
    		int v = e[i].to;
    		if(!dfn[v]){
    			tarjan(v,i);
    			low[x] = min(low[x],low[y]);
    			if(low[y] > dfn[x]) bridge[i] = bridge[i ^ 1] = 1;
    		}
    		else if(i != (in_edge ^ 1))
    			low[x] = min(low[x],dfn[v]);
    	}
    }
    

    割点判定(dfn[x]le low[y])

    void tarjan(int x){
        dfn[x] = low[x] = ++num; int flag = 0;
        for(int i = head[x];i;i = e[i].next){
            int v = e[i].to;
            if(!dfn[y]){
                tarjan(y);
                low[x] = min(low[x],low[y]);
                if(low[y] >= dfn[x]){
                    ++flag;
                    if(x != root || flag > 1) cut[x] = true;
    			}
            }
    	}
    }
    

    树链剖分

    void dfs1(int x,int f){
        dep[x] = dep[f] + 1; fa[x] = f; siz[x] = 1;
        for(int i = head[x];i;i = e[i].next){
            if(v == f) continue;
            dfs1(v,x);
            siz[x] += siz[v]; 
            if(siz[son[x]] < siz[v]) son[x] = v;
        }
    }
    void dfs2(int x,int tp){
        top[x] = tp;
        dfn[x] = ++cnt; rk[cnt] = x;
        if(son[x]) dfs2(son[x],tp);
        for(int i = head[x];i;i = e[i].next){
            int v = e[i].to;
            if(v == fa[x] || v == son[x]) continue;
            dfs2(v)
        }
    }
    //树剖求lca
    int lca(int x,int y){
    	int fx = top[x],fy = top[y];
    	while(fx != fy){
    		if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
    		x = fa[top[x]]; fx = top[x];
    	}
    	return dep[x] > dep[y] ? y : x;
    }
    

    (dijkstra)板子 求到(s)的单源最短路径

    priority_queue<pair<int,int> >q;
    void dijkstra(){
    	memset(d,0x3f,sizeof(d));
    	d[s] = 0;
    	q.push(make_pair(0,s));
    	while(q.size()){
    		int x = q.top().second; q.pop();
    		if(v[x]) continue;
    		v[x] = 1;
    		for(int i = head[x];i;i = e[i].next){
    			int y = e[i].to,z = e[i].w;
    			if(d[y] > d[x] + z){
    				d[y] = d[x] + z;
    				q.push(make_pair(-d[y],y));
    			}
    		}
    	}
    }
    

    (spfa)

    void spfa(){
    	memset(d,0x3f,sizeof(d));
    	d[s] = 0; queue<int> q;
    	q.push(s); vis[s] = 1;
    	while(q.size()){
    		int x = q.front(); q.pop();
    		vis[x] = 0;
    		for(int i = head[x];i;i = e[i].next){
    			int v = e[i].to,z = e[i].w;
    			if(d[v] > d[x] + z){
    				d[v] = d[x] + z;
    				if(!vis[v]) q.push(v),vis[v] = 1;
    			}
    		}
    	}
    }
    

    (floyed)传递闭包/距离 (bitset)优化

    bitset<N>f[N];
    for(int k = 1;k <= n;++k)
        for(int i = 1;i <= n;++i)
            for(int j = 1;j <= n;++j)
                f[i][j] |= f[i][k] & f[k][j];
    			//f[i][j] = min(f[i][j],min(f[i][k],f[k][j]));
    

    倍增$LCA $ (dfs)中顺便处理(LCA)

    void dfs1(int u,int f){
        dep[u] = dep[f] + 1; fa[u][0] = f;
        for(int j = 1;j <= 20;++j) fa[u][j] = fa[u][fa[u][j-1]];
        for(int i = head[u];i;i = e[i].next){
            int v = e[i].to; if(v == f) continue;
            dfs1(v,u);
        }
    }
    inline int lca(int x,int y){
        if(dep[x] < dep[y]) swap(x,y);
        for(int i = 20;i >= 0;--i){
            if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
            if(x == y) return x;
        }
        for(int i = 20;i >= 0;--i){
            if(fa[x][i] != fa[y][i]){
                x = fa[x][i];
                y = fa[y][i];
    		}
    	}
        return fa[x][0];
    }
    

    树上差分

    int dfs2(int x,int f){
    	for(int i = head[x];i;i = e[i].next){
    		int v = e[i].to;
    		if(v == f) continue;
    		dfs2(v,x);
    		cha[x] += cha[v];
    	}
    }
    for(int i = 1;i <= k;++i){
    		u = read(); v = read();
    		++cha[u]; ++cha[v]; cha[lca(u,v)] -= 2;//边差分
    	}
    for(int i = 1;i <= k;++i){
        u = read(); v = read(); int z = lca(u,v);
        ++cha[u]; ++cha[v]; --cha[z]; --cha[fa[z]];//点差分
    }
    

    已知中后序遍历,求先序遍历

    inline int find(char ch){
        for(int i = 0;i < len;++i)
            if(s1[i] == ch) return i;
    }
    void dfs(int l1,int r1,int l2,int r2){
        int m = find(s2[r2]);
        cout << s2[r2];
        if(m > l1) dfs(l1,m - 1,l2,r2 - r1 + m - 1);
        if(m < r1) dfs(m + 1,r1,l2 + m -l1.r2 -1);
    }
    

    板子整合计划2

    杂项 $ :C_nm=C_{n-1}{m-1}+C_{n-m}^m$ (vector的end)是越界的

    整体集合上的二分

    while(l <= r){
        int mid = l + r >>1;
        if(...) r = mid - 1;
        else r = mid + 1;
    }
    

    (e-DCC)

    void dfs(int x){
    	c[x] = dcc;
    	for(int i = head[x];i;i = e[i].next){
    		int v = e[i].to;
    		if(c[v] || bridge[i]) continue;
    		dfs(v);
    	}
    }
    main(){
    	for(int i = 1;i <= n;++i)
    		if(!c[i]){
    			++dcc;
    			dfs(i);
    		}
    	//dcc:有几个  c[i]:i belong to which gcc
        //还得用tarjan找桥
    }
    

    链表

    struct node{
    	int val,prev,next;
    }node[size];
    int head,tail,tot;
    int init(){
    	tot = 2;
    	head = 1;tail = 2;
    	node[head].next = tail;
    	node[tail].prev = head;
    }
    int insert(int p,int val){
    	q = ++tot;
    	node[q].val = val;
    	node[node[p].next].prev = q;
    	node[p].next = q;
    	node[q].next = p;
    }
    void remove(int p){
    	node[node[p].prev].next = node[p].next;
    	node[node[p].next] = node[p].prev;
    }
    void clear(){
    	memset(node,0,sizeof(node));
    	head = tail = tot = 0;
    }
    

    (O(nloglogn))埃氏筛

    void primes(int n){
        memser(vis,0,sizeof(vis));
        for(int i = 2;i <= n;++i){
            if(vis[v]) continue;
            printf("%d",i); //i是质数
            for(int j = i;j <= n/i;++j) vis[i * j] = 1;
    	}
    }
    

    (O(n))线性筛

    void primes(int n){
        memset(vis,0,sizeof(vis));
        num = 0;//素数数量
        for(int i = 2;i <= n;++i){
            if(!vis[i]) vis[i] = prime[++num] = i;
            for(int j = 1;j <= num;++j){
                //i有比prime[j]更小的质因子,或者超过n的范围,break
                if(prime[j] > vis[j] || prime[j] > n/i) break;
                vis[i * prime[j]] = prime[j];
            }
    	}
    }
    

    (exgcd)

    (ax+by=c) (gcd(a,b)|c)有解,通解为(x=frac cdx_0+frac bdt,y=frac cdy_0-frac adt,tin z,d=gcd(a,b))

    int exgcd(int a,int b,int &x,int &y){
        if(b == 0){x = 1,y = 0,return a;}
        int d = exgcd(b,a % b,x,y);
        int z = x;x = y;y = z - y * (a/b);
        return d;
    }
    

    欧拉筛phi

    int v[N],phi[N],prime[N];
    void euler(int n){
        memset(vis,0,sizeof(vis));
        num = 0;//质数
        for(int i = 2;i <= n;++i){
            if(!vis[i]){
                vis[i] = prime[++num]= i;
                phi[i] = i-1;
            }
        	for(int j = 1;j <= num;++j){
            	if(prime[j] > vis[i] || prime[j] > n/i) break;
                vis[i * prime[j]] = prime[j];
                phi[i * prime[j]] = phi[j];
                vis[i * prime[j]] = 
                    phi[i] * (i % prime[j] ? prime[j] - 1 : prime[j]);
        	}
        }
    }
    

    phi

    int phi(int n){
        int ans = n; int az = sqrt(n);
        for(int i = 2;i <= az;++i)
            if(n % i == 0)[
                ans = ans/ i * (i-1);
                while(n % i == 0) n /= i;
            ]
        if(n > 1) ans = ans / n * (n-1);
    }
    

    线性求逆元

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

    (O(n))(k)

    int find(int l,int r) {
        if(l == r && l == k) return a[k];
        if(l < r) {
            int i = l,j = r;
            int tmp = a[l];
            while(i < j) {
                while(i < j &&a[j] >= tmp) --j;
                if(i < j) swap(a[i],a[j]);
                while(i < j && a[i] <= tmp) ++i;
                if(i < j) swap(a[i],a[j]);
            }
            a[i] = tmp;
            if(i == k) return a[k];
            if(i > k) return find(l,i - 1);
            else return find(i + 1,r);
        }
    }
    
  • 相关阅读:
    Bootstrap3.0学习第八轮(工具Class)
    dependencies与dependencyManagement的区别
    灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断
    Linux平台安装MongoDB
    ubuntu 该软件包现在的状态极为不妥 error
    oracle vm突然黑屏了
    Oracle VM VirtualBox各种显示模式切换 热键
    where后一个条件和多个条件的查询速度
    String特殊值的判断方式
    将中文标点符号替换成英文标点符号
  • 原文地址:https://www.cnblogs.com/shikeyu/p/13565266.html
Copyright © 2011-2022 走看看