zoukankan      html  css  js  c++  java
  • 省选 考前模板

    线性筛的通用情况

    转载自 自为风月马前卒的博客

    //low[x]:x的最小质因子的次幂 
    vis[1] = low[1] = 1; H[1] = 初始化; 
    for(int i = 2; i <= N; i++) 
    {
        if(!vis[i]) prime[++tot] = i, mu[i] = -1, H[i] = 质数的情况, low[i] = i;
        for(int j = 1; j <= tot && i * prime[j] <= N; j++) 
        {
            vis[i * prime[j]] = 1;
            if(!(i % prime[j])) 
            {
                low[i * prime[j]] = (low[i] * prime[j]); 
                if(low[i] == i) H[i * prime[j]] = 特殊判断;
                else H[i * prime[j]] = H[i / low[i]] * H[prime[j] * low[i]];
                break;
            } 
            H[i * prime[j]] = H[i] * H[prime[j]];
            low[i * prime[j]] = prime[j];
        }
    }
    

    KMP字符串匹配

    int k = 0; nt[1] = 0;
    for (int i = 2; i <= lenb; ++i) 
    {
        while (k && b[k + 1] != b[i])k = nt[k];
        if (b[k + 1] == b[i])++k;
        nt[i] = k;
    }
    k = 0;
    for (int i = 1; i <= lena; ++i) 
    {
        while (k && b[k + 1] != a[i])k = nt[k];
        if (b[k + 1] == a[i])++k;
        if (k == lenb)pos[++ans] = i - lenb + 1;
    }									    
    

    manacher/马拉车 回文

    scanf("%s", s + 1); n = strlen(s + 1);                                              
    for (int i = 1, j = 0; i <= n; ++i)t[++j] = '*', t[++j] = s[i]; t[n + n + 1] = '*'; 
    t[0] = '$'; n = n + n + 1;                                                          
    for (int i = 1; i <= n; ++i)                                                        
    {                                                                                   
        p[i] = r > i ? min(r - i, p[2 * pos - i]) : 0;                                  
        while (t[i - p[i] - 1] == t[i + p[i] + 1])++p[i];                               
        if (i + p[i] > r)r = i + p[i], pos = i;                                         
    }																					
    

    PAM

    int cnt = 1, last, em;
    int get_fail(int x) 
    {
        while (s[em - len[x] - 1] != s[em])x = fail[x];
        return x;
    }
    int get_nt(int x) 
    {
        while (s[em - len[x] - 1] != s[em] || ((len[x] + 2) << 1) > len[cnt])x = fail[x];
        return x;
    }
    void Insert(int x) 
    {
        int f1 = get_fail(last);
        if (!tr[f1][x]) 
        {
            len[++cnt] = len[f1] + 2;
            fail[cnt] = tr[get_fail(fail[f1])][x];
            if (len[cnt] <= 2)nt[cnt] = fail[cnt];
            else nt[cnt] = tr[get_nt(nt[f1])][x];
            tr[f1][x] = cnt;
        }
        last = tr[f1][x];
    }
    fail[0] = 1; fail[1] = 0; len[0] = 0; len[1] = -1;
    for (int i = 1; i <= n; ++i)em = i, Insert(s[i] - 'a');
    

    AC 自动机

    void build(string s) 
    {
        int l = s.length(), now = 0;
        for (int i = 0; i < l; ++i) 
        {
            if (!AC[now].vis[s[i] - 'a'])AC[now].vis[s[i] - 'a'] = ++cnt;
            now = AC[now].vis[s[i] - 'a'];
        }
        ++AC[now].end;
    }
    queue<int>q;
    void Gfail() 
    {
        int u;
        for (int i = 0; i < 26; ++i)
            if (AC[0].vis[i]) AC[AC[0].vis[i]].fail = 0, q.push(AC[0].vis[i]);
        while (!q.empty()) 
        {
            u = q.front(); q.pop();
            for (int i = 0; i < 26; ++i)
                if (AC[u].vis[i]) 
                {
                    AC[AC[u].vis[i]].fail = AC[AC[u].fail].vis[i];
                    q.push(AC[u].vis[i]);
                } else AC[u].vis[i] = AC[AC[u].fail].vis[i];
        }
    }
    

    匈牙利二分图最大匹配

    bool dfs(int x) 
    {
        for (int i = head[x]; i; i = e[i].nt) 
        {
            if (vis[e[i].to])continue;
            vis[e[i].to] = 1;
            if (!mch[e[i].to] || dfs(mch[e[i].to])) 
            {
                mch[e[i].to] = x;
                return 1;
            }
        }
        return 0;
    }
    for (int i = 1; i <= n; ++i) 
    {
        memset(vis, 0, sizeof(vis));
        if (dfs(i))++ans;
    }
    

    网络最大流

    tot = 1;
    int bfs() 
    {
        int x;
        memset(dis, 0, sizeof(dis));
        while (!q.empty())q.pop();
        for (int i = 1; i <= n; ++i)cur[i] = head[i];
        dis[s] = 1; q.push(s);
        while (!q.empty()) 
        {
            x = q.front(); q.pop();
            for (int i = head[x]; i; i = nt[i])
                if (val[i] && !dis[to[i]]) 
                {
                    dis[to[i]] = dis[x] + 1;
                    if (to[i] == t)return 1;
                    q.push(to[i]);
                }
        }
        return 0;
    }
    int dinic(int x, int flow) 
    {
        if (x == t || !flow)return flow;
        int k, res = flow;
        for (int &i = cur[x]; i; i = nt[i])
            if (val[i] && dis[to[i]] == dis[x] + 1) 
            {
                k = dinic(to[i], min(val[i], res));
                if (!k)dis[to[i]] = 0;
                val[i] -= k; val[i ^ 1] += k;
                if (!(res -= k))break;
            }
        return flow - res;
    }
    while (bfs())ans += dinic(s, inf);
    

    最小费用最大流

    tot = 1;
    int SPFA() 
    {
        int x;
        memset(dis, 0x3f, sizeof(dis));
        memset(pre, -1, sizeof(pre));
        dis[s] = 0; q.push(s); vis[s] = 1;
        while (!q.empty()) 
        {
            x = q.front(); q.pop(); vis[x] = 0;
            for (int i = head[x]; i; i = nt[i])
                if (val[i] && dis[to[i]] > dis[x] + cost[i]) 
                {
                    dis[to[i]] = dis[x] + cost[i]; pre[to[i]] = i; from[to[i]] = x;
                    if (!vis[to[i]])q.push(to[i]), vis[to[i]] = 1;
                }
        }
        return pre[t] != -1;
    }
    void MFMC() 
    {
        int k;
        while (SPFA()) 
        {
            k = inf;
            for (int i = t; i != s; i = from[i])k = min(k, val[pre[i]]);
            ans1 += k; ans2 += dis[t] * k;
            for (int i = t; i != s; i = from[i])val[pre[i]] -= k, val[pre[i] ^ 1] += k;
        }
    }
    

    无源汇有上下界可行流

    int main()
    {
    	cin >> n >> m;
    	S = 0; T = n + 1;
    	for (int i = 1; i <= m; ++i)
    	{
    		x = read(); y = read(); L[i] = read(); r = read();
    		ADD(x, y, r - L[i]);
    		A[x] -= L[i]; A[y] += L[i];
    		c[i] = tot;
    	}
    	for (int i = 1; i <= n; ++i)
    		if (A[i] > 0)ADD(S, i, A[i]), sum += A[i];
    		else if (A[i])ADD(i, T, -A[i]);
    	while (bfs(S, T))
    		while (flow = dinic(S, inf))ans += flow;
    	if (ans != sum)return puts("NO") == 23333;
    	puts("YES");
    	for (int i = 1; i <= m; ++i)Write(L[i] + e[c[i]].cap, 1), putchar('
    ');
    	return 0;
    }
    

    有源汇有上下界最大流

    int main()
    {
    	cin >> n >> m >> S >> T;
    	SS = 0; TT = n + 1;
    	for (int i = 1; i <= m; ++i)
    	{
    		x = read(); y = read(); l = read(); r = read();
    		ADD(x, y, r - l);
    		A[x] -= l; A[y] += l;
    	}
    	for (int i = 1; i <= n; ++i)
    		if (A[i] > 0) {ADD(SS, i, A[i]); sum += A[i];}
    		else if (A[i])ADD(i, TT, -A[i]);
    	ADD(T, S, inf);
    	while (bfs(SS, TT))while (flow = dinic(SS, inf, TT))ans += flow;
    	if (ans != sum)return puts("please go home to sleep") == 23333;
    	ans = 0;
    	while (bfs(S, T))while (flow = dinic(S, inf, T))ans += flow;
    	cout << ans;
    	return 0;
    }
    

    有源汇有上下界最小流

    int main()
    {
    	cin >> n >> m >> S >> T;
    	SS = 0; TT = n + 1;
    	for (int i = 1; i <= m; ++i)
    	{
    		x = read(); y = read(); l = read(); r = read();
    		ADD(x, y, r - l);
    		A[x] -= l; A[y] += l;
    	}
    	for (int i = 1; i <= n; ++i)
    		if (A[i] > 0) {ADD(SS, i, A[i]); sum += A[i];}
    		else if (A[i])ADD(i, TT, -A[i]);
    	while (bfs(SS, TT))while (flow = dinic(SS, inf, TT))ans += flow;
    	ADD(T, S, inf);
    	while (bfs(SS, TT))while (flow = dinic(SS, inf, TT))ans += flow;
    	if (ans != sum)return puts("please go home to sleep") == 23333;
    	cout << e[tot].cap;
    	return 0;
    }
    

    左偏树(可并堆)

    struct dui {int val, fa, dis, ch[2];} tr[N << 1];
    int find(int x) {return x == tr[x].fa ? tr[x].fa : tr[x].fa = find(tr[x].fa);}
    int Merge(int x, int y) 
    {
        if (!x || !y)return x + y;
        if (tr[x].val > tr[y].val || (tr[x].val == tr[y].val && x > y))swap(x, y);
        tr[x].ch[1] = Merge(tr[x].ch[1], y); tr[tr[x].ch[1]].fa = x;
        if (tr[tr[x].ch[0]].dis < tr[tr[x].ch[1]].dis)swap(tr[x].ch[0], tr[x].ch[1]);
        tr[x].dis = tr[tr[x].ch[1]].dis + 1;
        return x;
    }
    void Delete(int x) 
    {
        tr[x].val = -1;
        tr[tr[x].ch[0]].fa = tr[x].ch[0]; tr[tr[x].ch[1]].fa = tr[x].ch[1];
        tr[x].fa = Merge(tr[x].ch[0], tr[x].ch[1]);
    }
    

    圆方树

    void Tarjan(int x)
    {
        dfn[x] = low[x] = ++cnt; zhan[++Top] = x;
        for (int i = Head[x]; i; i = Nt[i])
            if (!dfn[To[i]])
            {
                Tarjan(To[i]); low[x] = min(low[x], low[To[i]]);
                if (low[To[i]] >= dfn[x])
                {
                    add(++num, x); add(x, num);
                    int t;
                    do
                    {
                        t = zhan[Top--]; add(num, t); add(t, num);
                    } while (t != To[i]);
                }
            }
            else low[x] = min(low[x], dfn[To[i]]);
    }
    

    虚树

    int my(int a, int b) {return dfn[a] < dfn[b];}
    void build() 
    {
        int x, lca;
        sort(a + 1, a + 1 + k, my);
        if (a[1] != 1)zhan[top = 1] = 1;
        for (int i = 1; i <= k; ++i) 
        {
            x = a[i];
            if (top <= 1) {zhan[++top] = x; continue;}
            lca = LCA(zhan[top], x);
            if (lca == zhan[top]) {zhan[++top] = x; continue;}
            while (top > 1 && dep[lca] <= dep[zhan[top - 1]]) {add(zhan[top - 1], zhan[top], 0); --top;}
            if (lca != zhan[top])add(lca, zhan[top], 0), zhan[top] = lca;
            zhan[++top] = x;
        }
        while (top) {add(zhan[top - 1], zhan[top], 0); top--;}
    }
    

    dsu on tree

    void ADD(int x, int fa, int val) 
    {
        cnt[col[x]] += val;
        if (cnt[col[x]] > mx)mx = cnt[col[x]], nowans = col[x];
        else if (cnt[col[x]] == mx)nowans += col[x];
        for (int i = head[x]; i; i = nt[i])
            if (to[i] != fa && to[i] != Son)ADD(to[i], x, val);
    }
    void dfs2(int x, int fa, int opt) 
    {
        for (int i = head[x]; i; i = nt[i])
            if (to[i] != fa && to[i] != son[x])dfs2(to[i], x, 0);
        if (son[x])dfs2(son[x], x, 1), Son = son[x];
        ADD(x, fa, 1); Son = 0; ans[x] = nowans;
        if (!opt)ADD(x, fa, -1), nowans = 0, mx = 0;
    }
    

    Tarjan求割边

    void Tarjan(int x, int f) 
    {
        dfn[x] = low[x] = ++dfn_id;
        for (int i = head[x]; i; i = nt[i])
            if (i != f) 
            {
                if (!dfn[to[i]]) 
                {
                    Tarjan(to[i], i ^ 1), low[x] = min(low[x], low[to[i]]);
                    if (low[to[i]] > dfn[x])vis[i] = vis[i ^ 1] = 1;
                } else low[x] = min(low[x], dfn[to[i]]);
            }
    }
    

    Tarjan求割点

    void Tarjan(int x, int rt) 
    {
        int er = 0;
        dfn[x] = low[x] = ++cnt;
        for (int i = head[x]; i; i = e[i].nt) 
        {
            int v = e[i].to;
            if (!dfn[e[i].to]) 
            {
                Tarjan(v, rt);
                low[x] = min(low[x], low[v]);
                if (low[v] >= dfn[x] && x != rt)cut[x] = 1;
                if (x == rt)er++;
            }
            else low[x] = min(low[x], dfn[v]);
        }
        if (x == rt && er > 1)cut[x] = 1;
    }
    

    NTT

    void NTT(LL *A, int lim, int opt) 
    {
        for (int i = 0; i < lim; ++i)r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (lim >> 1) : 0);
        for (int i = 0; i < lim; ++i)if (i < r[i])swap(A[i], A[r[i]]);
        LL w, wn, x, y;
        for (int mid = 1, len = 2; len <= lim; mid <<= 1, len <<= 1) 
        {
            wn = ksm(opt == 1 ? G : Ginv, (mod - 1) / len, mod);
            for (int j = 0; j < lim; j += len) 
            {
                w = 1;
                for (int k = j; k < j + mid; ++k, w = w * wn % mod) 
                {
                    x = A[k]; y = A[k + mid] * w % mod;
                    A[k] = (x + y) % mod; A[k + mid] = (x - y + mod) % mod;
                }
            }
        }
        if (opt == 1)return;
        int ni = ksm(lim, mod - 2, mod);
        for (int i = 0; i < lim; ++i)A[i] = A[i] * ni % mod;
    }
    

    FFT

    void FFT(xu *A, int lim, int opt) 
    {
        for (int i = 0; i < lim; ++i)r[i] = (r[i >> 1] >> 1) | (i & 1 ? (lim >> 1) : 0);
        for (int i = 0; i < lim; ++i)if (i < r[i])swap(A[i], A[r[i]]);
        for (int mid = 1; mid < lim; mid <<= 1) 
        {
            xu wn(cos(PI / mid), opt * sin(PI / mid));
            for (int len = mid << 1, j = 0; j < lim; j += len) 
            {
                xu w((DB)1, (DB)0);
                for (int k = j; k < mid + j; ++k, w = w * wn) 
                {
                    xu a = A[k], b = w * A[k + mid];
                    A[k] = a + b;
                    A[k + mid] = a - b;
                }
            }
        }
        if (opt == 1)return;
        for (int i = 0; i < lim; ++i)A[i] = xu(A[i].x / lim , 0);
    }
    

    分治NTT

    void solve(int l, int r) 
    {
        if (l == r)return;
        int mid = (l + r) >> 1, len = r - l + 1;
        solve(l, mid);
        for (int i = 0; i < len; ++i)a[i] = b[i] = 0;
        for (int i = l; i <= mid; ++i)a[i - l] = f[i]; for (int i = 1; l + i <= r; ++i)b[i] = g[i];
        NTT(a, len, 1); NTT(b, len, 1);
        for (int i = 0; i < len; ++i)a[i] = (LL)a[i] * b[i] % mod;
        NTT(a, len, -1);
        for (int i = mid + 1; i <= r; ++i)(f[i] += a[i - l]) %= mod;
        solve(mid + 1, r);
    }
    

    多项式 INV LN EXP

    求逆:(B equiv 2B_0 -AB_0^2)

    求ln:(displaystyle int frac{A'}{A})

    求exp:(B equiv B_0(1-lnB_0+A))

    void INV(int siz, LL *A, LL *B) 
    {
        if (siz == 1) 
        {
            B[0] = ksm(A[0], mod - 2, mod);
            return;
        }
        INV((siz + 1) >> 1, A, B);
        int lim = 1;
        while (lim < (siz << 1))lim <<= 1;
        for (int i = 0; i < siz; ++i)c[i] = A[i];
        for (int i = siz; i < lim; ++i)c[i] = 0;
        NTT(c, lim, 1); NTT(B, lim, 1);
        for (int i = 0; i < lim; ++i)B[i] = B[i] * (2 - c[i] * B[i] % mod + mod) % mod;
        NTT(B, lim, -1);
        for (int i = siz; i < lim; ++i)B[i] = 0;
    }
    void MUL(LL *A, int n, LL *B, int m) 
    {
        int lim = 1;
        while (lim <= (n + m))lim <<= 1;
        NTT(A, lim, 1); NTT(B, lim, 1);
        for (int i = 0; i < lim; ++i)A[i] = A[i] * B[i] % mod;
        NTT(A, lim, -1);
    }
    LL LN_inv[N];
    void LN(int n, LL *A, LL *B) 
    {
        int lim = 1;
        while (lim <= (n << 1))lim <<= 1;
        for (int i = 1; i < n; ++i)B[i - 1] = A[i] * i % mod;
        for (int i = n - 1; i < lim; ++i)B[i] = 0;
        for (int i = 0; i < lim; ++i)LN_inv[i] = 0;
        INV(n, A, LN_inv);
        MUL(B, n, LN_inv, n);
        for (int i = lim - 1; i >= 1; --i)B[i] = B[i - 1] * ksm(i, mod - 2, mod);
        B[0] = 0;
    }
    LL ln[N];
    void EXP(int siz, LL *A, LL *B) 
    {
        if (siz == 1) 
        {
            B[0] = 1;
            return;
        }
        EXP((siz + 1) >> 1, A, B);
        LN(siz, B, ln);
        int lim = 1;
        while (lim < (siz << 1))lim <<= 1;
        for (int i = 0; i < siz; ++i)ln[i] = A[i] - ln[i];
        ln[0]++;
        for (int i = siz; i < lim; ++i)ln[i] = B[i] = 0;
        MUL(B, siz, ln, siz);
    }
    

    FWT

    void GET()
    {
        for(int i=0;i<n;++i)a[i]=(LL)a[i]*b[i]%mod;
    }
    void OR(LL *A, int opt) 
    {
        for (int mid = 1, len = 2; len <= n; mid <<= 1, len <<= 1)
            for (int i = 0; i < n; i += len)
                for (int j = i; j < i + mid; ++j)
                    (A[j + mid] += A[j] * opt) %= mod;
    }
    void AND(LL *A, int opt) 
    {
        for (int mid = 1, len = 2; len <= n; mid <<= 1, len <<= 1)
            for (int i = 0; i < n; i += len)
                for (int j = i; j < i + mid; ++j)
                    (A[j] += A[j + mid] * opt) %= mod;
    }
    void XOR(LL *A, int opt) 
    {
        int a, b;
        for (int mid = 1, len = 2; len <= n; mid <<= 1, len <<= 1)
            for (int i = 0; i < n; i += len)
                for (int j = i; j < i + mid; ++j)
                    a = A[j], b = A[j + mid], A[j] = (LL)(a + b) * opt % mod, A[j + mid] = (LL)(a - b) * opt % mod;
    }
    OR(a, 1); OR(b, 1); GET(); OR(a, mod - 1);
    AND(a, 1); AND(b, 1); GET(); AND(a, mod - 1);
    XOR(a, 1); XOR(b, 1); GET(); XOR(a, (mod + 1) / 2);
    

    子集卷积

    inline int yi(int x) {int res = 0; while (x)res += x & 1, x >>= 1; return res;}
    void OR(int *A, int lim, int opt) 
    {
        for (int mid = 1, len = 2; len <= lim; mid <<= 1, len <<= 1)
            for (int j = 0; j < lim; j += len)
                for (int k = j; k < j + mid; ++k)
                    (A[k + mid] += A[k] * opt) %= mod;
    }
    int main() 
    {
        cin >> m; n = 1 << m;
        for (int i = 0; i < n; ++i)scanf("%d", &a[yi(i)][i]);
        for (int i = 0; i < n; ++i)scanf("%d", &b[yi(i)][i]);
        for (int i = 0; i <= m; ++i)OR(a[i], n, 1), OR(b[i], n, 1);
        for (int i = 0; i < n; ++i)
            for (int j = 0; j <= m; ++j)
                for (int k = 0; k <= j; ++k)c[j][i] = ((LL)c[j][i] + (LL)a[k][i] * b[j - k][i]) % mod;
        for (int i = 0; i <= m; ++i)OR(c[i], n, -1);
        for (int i = 0; i < n; ++i)printf("%d ", (c[yi(i)][i] + mod) % mod);
        return 0;
    }
    

    自适应辛普森

    辛普森公式:(displaystyle int_{a}^{b}f(x)dx approx frac{(b-a)(f(a)+f(b)+4f(frac{a+b}{2}))}{6})

    inline DB simpson(DB l , DB r) {return (f(l) + 4 * f((l + r) / 2) + f(r)) * (r - l) / 6;}
    inline DB jue(DB x) {return x > 0 ? x : -x;}
    DB asr(DB l, DB r, DB eps, DB ans) 
    {
        DB mid = (l + r) / 2, L = simpson(l, mid), R = simpson(mid, r);
        if (jue(L + R - ans) <= eps * 15)return L + R + (L + R - ans) / 15;
        return asr(l, mid, eps / 2, L) + asr(mid, r, eps / 2, R);
    }
    

    Matrix-Tree 定理(矩阵树定理)

    详见博客

    for (int i = 2, inv, tmp; i <= n; ++i)
    {
        for (int j = i + 1; j <= n; ++j)
            if (!a[i][i] && a[j][i]) {ans = -ans; swap(a[i], a[j]); break;}
        inv = ksm(a[i][i], mod - 2, mod);
        for (int j = i + 1; j <= n; ++j)
        {
            tmp = (LL)a[j][i] * inv % mod;
            for (int k = i; k <= n; ++k)a[j][k] = (a[j][k] - (LL)a[i][k] * tmp % mod) % mod;
        }
    }
    

    二维凸包

    inline int my1(dian a, dian b) {return a.x == b.x ? a.y < b.y : a.x < b.x;}
    inline int my2(dian a, dian b) 
    {
        int tmp = dump(cross(a - e[1], b - e[1]));
        if (tmp > 0)return 1;
        else if (tmp == 0 && dump(dis(a, e[1]) - dis(b, e[1])) < 0)return 1;
        return 0;
    }
    inline void TU_BAO() 
    {
        sort(e + 1, e + 1 + n, my1);
        sort(e + 2, e + 1 + n, my2);
        zhan[top = 1] = e[1];
        for (int i = 2; i <= n; ++i) 
        {
            while (top > 1 && dump(cross(e[i] - zhan[top - 1], zhan[top] - zhan[top - 1])) >= 0)--top;
            zhan[++top] = e[i];
        }
    }
    

    半平面交

    friend bool operator <(const xian &a, const xian &b) {return a.ang < b.ang;}
    DB cross(dian a, dian b) {return a.x * b.y - a.y * b.x;}
    int onleft(xian s, dian a) {return cross(s.v, a - s.p) > 0;}
    dian linemeet(xian a, xian b) {return a.p + a.v * (cross(b.v, a.p - b.p) / cross(a.v, b.v));}
    int hpi(xian *L, int n) 
    {
        sort(L + 1, L + 1 + n);
        int head, tail;
        sta[head = tail = 1] = L[1];
        for (int i = 2; i <= n; ++i) 
        {
            while (head < tail && !onleft(L[i], p[tail - 1]))tail--;
            while (head < tail && !onleft(L[i], p[head]))head++;
            sta[++tail] = L[i];
            if (!dump(cross(sta[tail].v, sta[tail - 1].v))) 
            {
                tail--;
                if (onleft(sta[tail], L[i].p))sta[tail] = L[i];
            }
            if (head < tail)p[tail - 1] = linemeet(sta[tail], sta[tail - 1]);
        }
        while (head < tail && !onleft(sta[head], p[tail - 1]))tail--;
        if (tail <= head + 1)return 0;
        p[tail] = linemeet(sta[tail], sta[head]);
        for (int i = head; i <= tail; ++i)Ans[i - head + 1] = p[i];
        return tail - head + 1;
    }
    

    平衡树splay

    int isr(int x) {return x == tr[tr[x].fa].ch[1];}
    int js(int x) {return tr[tr[x].ch[0]].siz + 1;}
    void updata(int x) {tr[x].siz = tr[tr[x].ch[0]].siz + tr[tr[x].ch[1]].siz + 1;}
    void New(int x, int val) 
    {
        tr[x].ch[0] = tr[x].ch[1] = tr[x].fa = 0;
        tr[x].val = val; tr[x].siz = 1;
    }
    void rotate(int x) 
    {
        int y = tr[x].fa, z = tr[y].fa, k = isr(x);
        if (y != root)tr[z].ch[isr(y)] = x;
        else root = x;
        tr[y].ch[k] = tr[x].ch[!k]; tr[tr[y].ch[k]].fa = y;
        tr[x].ch[!k] = y; tr[y].fa = x; tr[x].fa = z;
        updata(y); updata(x);
    }
    void Splay(int x) 
    {
        while (x != root) 
        {
            if (tr[x].fa != root)rotate(isr(x) == isr(tr[x].fa) ? tr[x].fa : x);
            rotate(x);
        }
    }
    void Insert(int val) 
    {
        if (!root) 
        {
            root = (top ? zhan[top--] : ++cnt);
            New(root, val);
            return;
        }
        int now = root, fa = 0;
        while (now) {fa = now; now = tr[now].ch[val > tr[now].val];}
        now = (top ? zhan[top--] : ++cnt); New(now, val);
        tr[fa].ch[tr[now].val > tr[fa].val] = now; tr[now].fa = fa;
        Splay(now);
    }
    void Merge(int &x, int y, int fa) 
    {
        if (x)tr[x].fa = fa;
        if (y)tr[y].fa = fa;
        if (!x || !y) {x = x + y; return;}
        Merge(tr[x].ch[1], y, x);
        updata(x);
    }
    void Delete(int val) 
    {
        int now = root;
        while (now && tr[now].val != val)now = tr[now].ch[val > tr[now].val];
        if (!now)return;
        zhan[++top] = now; Splay(now);
        Merge(tr[now].ch[0], tr[now].ch[1], 0);
        root = tr[now].ch[0];
    }
    int Rank(int val) 
    {
        int now = root, fa = 0, res = 0;
        while (now) 
        {
            fa = now;
            if (val <= tr[now].val)now = tr[now].ch[0];
            else {res += js(now); now = tr[now].ch[1];}
        }
        Splay(fa);
        return res + 1;
    }
    int Kth(int k) 
    {
        int now = root;
        while (now && js(now) != k) 
        {
            if (k < js(now))now = tr[now].ch[0];
            else {k -= js(now); now = tr[now].ch[1];}
        }
        Splay(now);
        return tr[now].val;
    }
    int Pre(int val) 
    {
        int now = root, last = 0;
        while (now) 
        {
            if (val > tr[now].val) {last = now; now = tr[now].ch[1];}
            else now = tr[now].ch[0];
        }
        if (last) {Splay(last); return tr[last].val;}
        return -1;
    }
    int Next(int val) 
    {
        int now = root, last = 0;
        while (now) 
        {
            if (val < tr[now].val) {last = now; now = tr[now].ch[0];}
            else now = tr[now].ch[1];
        }
        if (last) {Splay(last); return tr[last].val;}
        return -1;
    }
    

    splay维护序列

    void pushup(int x) 
    {
        siz[x] = siz[lson] + siz[rson] + 1;
        mx[x] = val[x];
        if (lson)mx[x] = max(mx[x], mx[lson]);
        if (rson)mx[x] = max(mx[x], mx[rson]);
    }
    void pushdown(int x) 
    {
        if (rev[x]) 
        {
            swap(ch[lson][0], ch[lson][1]); swap(ch[rson][0], ch[rson][1]);
            rev[lson] ^= 1; rev[rson] ^= 1; rev[x] = 0;
        }
        if (tag[x]) 
        {
            val[lson] += tag[x]; mx[lson] += tag[x]; val[rson] += tag[x]; mx[rson] += tag[x];
            tag[lson] += tag[x]; tag[rson] += tag[x]; tag[x] = 0;
        }
    }
    int isr(int x) {return ch[fa[x]][1] == x;}
    void rotate(int x, int &to) 
    {
        int y = fa[x], z = fa[y], k = isr(x);
        if (y == to)to = x;
        else ch[z][isr(y)] = x;
        ch[y][k] = ch[x][!k]; fa[ch[y][k]] = y;
        ch[x][!k] = y; fa[y] = x; fa[x] = z;
        pushup(y); pushup(x);
    }
    void splay(int x, int &to) 
    {
        while (x != to) 
        {
            if (fa[x] != to)rotate(isr(x) == isr(fa[x]) ? fa[x] : x, to);
            rotate(x, to);
        }
    }
    int build(int l, int r) 
    {
        if (l > r)return 0;
        int mid = (l + r) >> 1, x = ++cnt; siz[x] = 1;
        lson = build(l, mid - 1); fa[lson] = x;
        rson = build(mid + 1, r); fa[rson] = x;
        pushup(x);
        return x;
    }
    int find(int x, int k) 
    {
        while (1) 
        {
            pushdown(x);
            if (k <= siz[lson])x = lson;
            else 
            {
                k -= siz[lson] + 1;
                if (!k)return x;
                x = rson;
            }
        }
    }
    int split(int x, int y) 
    {
        x = find(root, x); y = find(root, y);
        splay(x, root); splay(y, ch[root][1]);
        return ch[y][0];
    }
    

    LCT

    inline int isr(int x) {return ch[fa[x]][1] == x;}
    inline int isroot(int x) {return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}
    void pushup(int x) {sum[x] = val[x] ^ sum[lson] ^ sum[rson];}
    void pushdown(int x) 
    {
        if (rev[x]) 
        {
            swap(ch[lson][0], ch[lson][1]); swap(ch[rson][0], ch[rson][1]);
            rev[lson] ^= 1; rev[rson] ^= 1; rev[x] = 0;
        }
    }
    void upd(int x) 
    {
        if (!isroot(x))upd(fa[x]); pushdown(x);
    }
    void rot(int x) 
    {
        int y = fa[x], z = fa[y], k = isr(x);
        if (!isroot(y))ch[z][isr(y)] = x;
        ch[y][k] = ch[x][!k]; fa[ch[y][k]] = y;
        ch[x][!k] = y; fa[y] = x; fa[x] = z;
        pushup(y); pushup(x);
    }
    void Splay(int x) 
    {
        upd(x);
        while (!isroot(x)) 
        {
            if (!isroot(fa[x]))rot(isr(x) == isr(fa[x]) ? fa[x] : x);
            rot(x);
        }
    }
    void access(int x) 
    {
        int t = 0;
        while (x) {Splay(x); rson = t; pushup(x); t = x; x = fa[x];}
    }
    void make_root(int x) 
    {
        access(x); Splay(x);
        swap(lson, rson); rev[x] ^= 1;
    }
    void link(int x, int y) {make_root(x); fa[x] = y;}
    void cut(int x, int y) {make_root(y); access(x); Splay(x); lson = fa[y] = 0;}
    int find(int x) 
    {
        access(x); Splay(x);
        while (lson)pushdown(x), x = lson;
        return x;
    }
    void change(int x, int v) {Splay(x); sum[x] ^= val[x]; val[x] = v; sum[x] ^= val[x];}
    int main() 
    {
        cin >> n >> m;
        for (int i = 1; i <= n; ++i)scanf("%d", &val[i]);
        while (m--) 
        {
            scanf("%d%d%d", &opt, &x, &y);
            if (opt == 0) 
            {
                make_root(x); access(y); Splay(y);
                printf("%d
    ", sum[y]);
            } else if (opt == 1) {if (find(x) != find(y))link(x, y);}
            else if (opt == 2) {if (find(x) == find(y) && (fa[x] == y || fa[y] == x))cut(x, y);}
            else change(x, y);
        }
        return 0;
    }
    
  • 相关阅读:
    SpringBoot启动类踩坑
    数组作业
    多态的使用
    intellij idea怎么设置软件启动时选择项目进入
    方法的递归调用
    取一个数字数字后4位的和
    day09作业
    java 随机数
    java 方法
    java 循环作业
  • 原文地址:https://www.cnblogs.com/wljss/p/13150351.html
Copyright © 2011-2022 走看看