3.23-4.6做题情况

上周月考没怎么做题,再加上忘了写,就两周放在一起了

魔术球问题:网络流24题,最大流
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 3500,maxm = 3e4 + 50,inf = 1e9;
int n,m,S,T,x,y,z,cnt = 1,tot,now,ans,d[maxn],t[maxn],last[maxn],nxt[maxn],head[maxn];
queue <int> q;
struct Edge{
    int v,nxt,w;
}e[2 * maxm];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
inline void insert(int x,int y,int z){
    cnt ++,e[cnt].v = y,e[cnt].w = z,e[cnt].nxt = last[x],last[x] = cnt;
}
inline void add(int x,int y,int z){
    insert(x,y,z);
    insert(y,x,0);
}
bool bfs(){
    for(int i = 0; i <= 2 * now + 1; i ++) d[i] = -1,t[i] = last[i];
    d[S] = 0,q.push(S);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i = last[u]; i; i = e[i].nxt){
            int v = e[i].v;
            if(d[v] == -1 && e[i].w) d[v] = d[u] + 1,q.push(v);
        }
    }
    if(d[T] != -1) return 1;
    else return 0;
}
int dfs(int u,int k){
    if(u == T) return k;
    if(!k) return 0;
    int s = 0;
    for(int i = t[u]; i; i = e[i].nxt){
        t[u] = i;
        int v = e[i].v;
        if(d[v] == d[u] + 1){
            int p = dfs(v,min(k,e[i].w));
            e[i].w -= p,e[i ^ 1].w += p,s += p,k -= p;
            if(p) nxt[u / 2] = v / 2;
            if(!k) break;
        }
    }
    return s;
}
int Dinic(){
    int s = 0;
    while(bfs()) s += dfs(S,inf);
    return s;
}
int main(){
    n = read(),S = 0,T = 1;
    while(tot <= n){
        now ++;
        add(S,2 * now,1),add(2 * now + 1,T,1);
        for(int i = sqrt(now) + 1; i * i < 2 * now; i ++) add(2 * (i * i - now),2 * now + 1,1);
        if(!Dinic()) tot ++,head[tot] = now;
    }
    printf("%d\n",now - 1);
    for(int i = 1; i <= n; i ++){
        for(int u = head[i]; u; u = nxt[u]) printf("%d ",u);
        printf("\n");
    }
    return 0;
}
Dynamic Rankings: 树状数组套主席树,离散化
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 50,maxm = 400 * maxn;
int n,m,len,cnt,tot1,tot2,t1[maxn],t2[maxn],a[maxn],t[2 * maxn],qx[maxn],qy[maxn],qk[maxn],rt[maxn],ls[maxm],rs[maxm],val[maxm];
char qc[maxn];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
void modify(int p,int k,int &x,int l,int r){
    if(!x) x = ++cnt;
    val[x] += k;
    if(l == r) return;
    int mid = (l + r) / 2;
    if(p <= mid) modify(p,k,ls[x],l,mid);
    else modify(p,k,rs[x],mid + 1,r);
}
int find(int l,int r,int k){
    if(l == r) return l;
    int s = 0,mid = (l + r) / 2;
    for(int i = 1; i <= tot1; i ++) s -= val[ls[t1[i]]];
    for(int i = 1; i <= tot2; i ++) s += val[ls[t2[i]]];
    if(k <= s){
        for(int i = 1; i <= tot1; i ++) t1[i] = ls[t1[i]];
        for(int i = 1; i <= tot2; i ++) t2[i] = ls[t2[i]];
        return find(l,mid,k);
    }else{
        for(int i = 1; i <= tot1; i ++) t1[i] = rs[t1[i]];
        for(int i = 1; i <= tot2; i ++) t2[i] = rs[t2[i]];
        return find(mid + 1,r,k - s);
    }
}
inline int lowbit(int x){
    return x & (-x);
}
void update(int x,int k){
    int p = lower_bound(t + 1,t + len + 1,a[x]) - t;
    while(x <= n){
        modify(p,k,rt[x],1,len);
        x += lowbit(x);
    }
}
int query(int l,int r,int k){
    tot1 = tot2 = 0,l --;
    while(l) t1[++tot1] = rt[l],l -= lowbit(l);
    while(r) t2[++tot2] = rt[r],r -= lowbit(r);
    return find(1,len,k);
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= n; i ++) a[i] = t[++len] = read();
    for(int i = 1; i <= m; i ++){
        cin >> qc[i];
        if(qc[i] == 'C') qx[i] = read(),qy[i] = read(),t[++len] = qy[i];
        else qx[i] = read(),qy[i] = read(),qk[i] = read();
    }
    sort(t + 1,t + len + 1);
    len = unique(t + 1,t + len + 1) - t - 1;
    for(int i = 1; i <= n; i ++) update(i,1);
    for(int i = 1; i <= m; i ++){
        if(qc[i] == 'C'){
            update(qx[i],-1);
            a[qx[i]] = qy[i];
            update(qx[i],1);
        }else printf("%d\n",t[query(qx[i],qy[i],qk[i])]);
    }
    return 0;
}
[ZJOI2013]K大数查询: 权值线段树套区间线段树,离散化
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 5e4 + 50,maxm = 400 * maxn;
int n,m,cnt,len,qt[maxn],ql[maxn],qr[maxn],t[2 * maxn],rt[8 * maxn],ls[maxm],rs[maxm];
long long qk[maxn],num[maxm],tag[maxm];
inline long long read(){
    register long long x = 0,f = 1;
    register char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x * f;
}
inline void push_up(int x){
    num[x] = num[ls[x]] + num[rs[x]];
}
inline void push_down(int x,int l,int r){
    if(!ls[x]) ls[x] = ++cnt;
    if(!rs[x]) rs[x] = ++cnt;
    register int mid = (l + r) / 2;
    num[ls[x]] += (mid - l + 1) * tag[x],num[rs[x]] += (r - mid) * tag[x];
    tag[ls[x]] += tag[x],tag[rs[x]] += tag[x],tag[x] = 0;
}
inline void modify(int L,int R,int &x,int l,int r){
    if(!x) x = ++cnt;
    if(L <= l && R >= r){
        num[x] += r - l + 1,tag[x] ++;
        return;
    }
    if(tag[x]) push_down(x,l,r);
    register int mid = (l + r) / 2;
    if(L <= mid) modify(L,R,ls[x],l,mid);
    if(R > mid) modify(L,R,rs[x],mid + 1,r);
    push_up(x);
}
inline long long sum(int L,int R,int x,int l,int r){
    if(!x) return 0;
    if(L <= l && R >= r) return num[x];
    if(tag[x]) push_down(x,l,r);
    register int mid = (l + r) / 2;
    register long long s = 0;
    if(L <= mid) s += sum(L,R,ls[x],l,mid);
    if(R > mid) s += sum(L,R,rs[x],mid + 1,r);
    return s;
}
inline void update(int L,int R,int k,int x,int l,int r){
    modify(L,R,rt[x],1,n);
    if(l == r) return;
    register int mid = (l + r) / 2;
    if(k <= mid) update(L,R,k,x << 1,l,mid);
    else update(L,R,k,x << 1 | 1,mid + 1,r);
}
inline int query(int L,int R,long long k,int x,int l,int r){
    if(l == r) return t[l];
    register int mid = (l + r) / 2;
    register long long s = sum(L,R,rt[x << 1 | 1],1,n);
    if(s < k) return query(L,R,k - s,x << 1,l,mid);
    else return query(L,R,k,x << 1 | 1,mid + 1,r);
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= m; i ++){
        qt[i] = read(),ql[i] = read(),qr[i] = read(),qk[i] = read();
        if(qt[i] == 1) t[++len] = qk[i];
    }
    sort(t + 1,t + len + 1);
    len = unique(t + 1,t + len + 1) - t - 1;
    for(register int i = 1; i <= m; i ++){
        if(qt[i] == 1) update(ql[i],qr[i],lower_bound(t + 1,t + len + 1,qk[i]) - t,1,1,len);
        else printf("%d\n",query(ql[i],qr[i],qk[i],1,1,len));
    }
    return 0;
}
Count on a tree: 主席树,LCA,离散化
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 50,maxm = 30 * maxn;
int n,m,x,y,k,cnt,tot,num[maxn],t[maxn],d[maxn],last[maxn],f[maxn][20],rt[maxn],ls[maxm],rs[maxm],val[maxm];
struct edge{
    int v,nxt;
}e[2 * maxn];
int read(){
    int x = 0,f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x * f;
}
inline void add(int x,int y){
    cnt ++,e[cnt].v = y,e[cnt].nxt = last[x],last[x] = cnt;
}
void modify(int p,int k,int &x,int l,int r,int last){
    x = ++tot,val[x] = val[last] + k,ls[x] = ls[last],rs[x] = rs[last];
    if(l == r) return;
    int mid = (l + r) / 2;
    if(p <= mid) modify(p,k,ls[x],l,mid,ls[last]);
    else modify(p,k,rs[x],mid + 1,r,rs[last]);
}
int query(int x,int y,int a,int b,int k,int l,int r){
    if(l == r) return t[l];
    int mid = (l + r) / 2,t = val[ls[x]] + val[ls[y]] - val[ls[a]] - val[ls[b]];
    if(k <= t) return query(ls[x],ls[y],ls[a],ls[b],k,l,mid);
    else return query(rs[x],rs[y],rs[a],rs[b],k - t,mid + 1,r);
}
void dfs(int u,int fa){
    d[u] = d[fa] + 1,f[u][0] = fa;
    modify(lower_bound(t + 1,t + n + 1,num[u]) - t,1,rt[u],1,n,rt[fa]);
    for(int i = 1; i <= 17; i ++) f[u][i] = f[f[u][i - 1]][i - 1];
    for(int i = last[u]; i; i = e[i].nxt){
        int v = e[i].v;
        if(v == fa) continue;
        dfs(v,u);
    }
}
int Lca(int x,int y){
    if(d[x] < d[y]) swap(x,y);
    for(int i = 17; i >= 0; i --) if(d[f[x][i]] >= d[y]) x = f[x][i];
    if(x == y) return x;
    for(int i = 17; i >= 0; i --) if(f[x][i] != f[y][i]) x = f[x][i],y = f[y][i];
    return f[x][0];
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= n; i ++) num[i] = read(),t[i] = num[i];
    sort(t + 1,t + n + 1);
    for(int i = 1; i < n; i ++){
        x = read(),y = read();
        add(x,y),add(y,x);
    }
    dfs(1,0);
    for(int i = 1; i <= m; i ++){
        x = read(),y = read(),k = read();
        int t = Lca(x,y);
        printf("%d\n",query(rt[x],rt[y],rt[t],rt[f[t][0]],k,1,n));
    }
    return 0;
}
Anton and Permutation: 树状数组套主席树
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 2e5 + 50,maxm = 100 * maxn;
int n,m,x,y,cnt,num[maxn],rt[maxn],ls[maxm],rs[maxm],val[maxm];
long long ans;
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
void modify(int p,int k,int &x,int l,int r){
    if(!x) x = ++cnt;
    val[x] += k;
    if(l == r) return;
    int mid = (l + r) / 2;
    if(p <= mid) modify(p,k,ls[x],l,mid);
    else modify(p,k,rs[x],mid + 1,r);
}
int sum(int L,int R,int x,int l,int r){
    if(!x) return 0;
    if(L <= l && R >= r) return val[x];
    int mid = (l + r) / 2,s = 0;
    if(L <= mid)  s += sum(L,R,ls[x],l,mid);
    if(R > mid) s += sum(L,R,rs[x],mid + 1,r);
    return s;
}
inline int lowbit(int x){
    return x & (-x);
}
void update(int x,int k){
    for(int i = x; i <= n; i += lowbit(i)){
        if(num[x]) modify(num[x],-1,rt[i],1,n);
        modify(k,1,rt[i],1,n);
    }
}
int query(int x,int y,int l,int r){
    if(x > y) return 0;
    int s = 0;
    x --;
    while(x) s -= sum(l,r,rt[x],1,n),x -= lowbit(x);
    while(y) s += sum(l,r,rt[y],1,n),y -= lowbit(y);
    return s;
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= n; i ++) update(i,i),num[i] = i;
    for(int i = 1; i <= m; i ++){
        x = read(),y = read();
        if(x == y){
            printf("%lld\n",ans);
            continue;
        }
        if(x > y) swap(x,y);
        if(num[x] < num[y]) ans ++;
        else ans --;
        ans += query(x + 1,y - 1,num[x],n) - query(x + 1,y - 1,1,num[x]);
        ans += query(x + 1,y - 1,1,num[y]) - query(x + 1,y - 1,num[y],n);
        update(x,num[y]),update(y,num[x]);
        swap(num[x],num[y]);
        printf("%lld\n",ans);
    }
    return 0;
}
[国家集训队]middle: 二分,离散化,可持久化区间线段树

特别巧妙的一道题,将中位数转化为区间和,令当前区间内大于x的数为1,小于当前数的为-1,则区间和等于0时x便是中位数。考虑二分答案x,将[a,d]按上述规则染色,则x在当前询问可行等价于所有区间的和的最大值大于等于0,又[b,c]是必选的,所以只需要分别求[a,b - 1],[c + 1,d]的前后缀最大值,即我们需要对每一个x维护染色后的区间前后缀最大值。显然要先离散化,然后考虑对每一个x建线段树,但空间不够,发现对于相邻的两数x、x - 1只有第x位不同,使用可持久化,则空间复杂度nlogn,可以接受。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 2e4 + 50,maxm = 100 * maxn;
int n,q,cnt,last,t[4],rt[maxn],ls[maxm],rs[maxm],sum[maxm],pre[maxm],suf[maxm];
struct node{
    int num,pos;
}a[maxn];
int read(){
    int x = 0,f = 1;
    char c = getchar();
    while(c < '0' || c > '9'){
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x * f;
}
bool cmp(node x,node y){
    return x.num < y.num;
}
inline void push_up(int x){
    pre[x] = max(pre[ls[x]],sum[ls[x]] + pre[rs[x]]);
    suf[x] = max(suf[rs[x]],sum[rs[x]] + suf[ls[x]]);
    sum[x] = sum[ls[x]] + sum[rs[x]];
}
void build(int &x,int l,int r){
    x = ++cnt;
    if(l == r){
        sum[x] = 1,pre[x] = suf[x] = sum[x];
        return;
    }
    int mid = (l + r) / 2;
    build(ls[x],l,mid),build(rs[x],mid + 1,r);
    push_up(x);
}
void modify(int p,int k,int &x,int l,int r,int last){
    x = ++cnt,ls[x] = ls[last],rs[x] = rs[last];
    if(l == r){
        sum[x] = k,pre[x] = suf[x] = sum[x];
        return;
    }
    int mid = (l + r) / 2;
    if(p <= mid) modify(p,k,ls[x],l,mid,ls[last]);
    else modify(p,k,rs[x],mid + 1,r,rs[last]);
    push_up(x);
}
int query_sum(int L,int R,int x,int l,int r){
    if(L <= l && R >= r) return sum[x];
    int mid = (l + r) / 2,s = 0;
    if(L <= mid) s += query_sum(L,R,ls[x],l,mid);
    if(R > mid) s += query_sum(L,R,rs[x],mid + 1,r);
    return s;
}
int query_pre(int L,int R,int x,int l,int r){
    if(L <= l && R >= r) return pre[x];
    int mid = (l + r) / 2;
    if(L <= mid && R > mid) return max(query_pre(L,R,ls[x],l,mid),query_sum(L,mid,x,l,r) + query_pre(L,R,rs[x],mid + 1,r));
    else if(L <= mid) return query_pre(L,R,ls[x],l,mid);
    else if(R > mid) return query_pre(L,R,rs[x],mid + 1,r);
}
int query_suf(int L,int R,int x,int l,int r){
    if(L <= l && R >= r) return suf[x];
    int mid = (l + r) / 2;
    if(L <= mid && R > mid) return max(query_suf(L,R,rs[x],mid + 1,r),query_sum(mid + 1,R,x,l,r) + query_suf(L,R,ls[x],l,mid));
    else if(L <= mid) return query_suf(L,R,ls[x],l,mid);
    else if(R > mid) return query_suf(L,R,rs[x],mid + 1,r);
}
bool check(int x,int a,int b,int c,int d){
    int s = query_sum(b,c,rt[x],1,n);
    if(a <= b - 1) s += max(0,query_suf(a,b - 1,rt[x],1,n));
    if(c + 1 <= d) s += max(0,query_pre(c + 1,d,rt[x],1,n));
    if(s >= 0) return 1;
    else return 0;
}
int main(){
    n = read();
    for(int i = 1; i <= n; i ++) a[i].num = read(),a[i].pos = i;
    sort(a + 1,a + n + 1,cmp);
    build(rt[1],1,n);
    for(int i = 2; i <= n; i ++) modify(a[i - 1].pos,-1,rt[i],1,n,rt[i - 1]);
    q = read();
    while(q --){
        for(int i = 0; i < 4; i ++) t[i] = (read() + last) % n + 1;
        sort(t,t + 4);
        int l = 1,r = n;
        while(l < r){
            int mid = (l + r + 1) / 2;
            if(check(mid,t[0],t[1],t[2],t[3])) l = mid;
            else r = mid - 1;
        }
        printf("%d\n",last = a[l].num);
    }
    return 0;
}
[SDOI2011]染色: 树剖,线段树,LCT
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 1e5 + 50;
int n,m,x,y,k,cnt,tot,Lc,Rc,a[maxn],last[maxn],size[maxn],d[maxn],f[maxn],son[maxn],top[maxn],pos[maxn];
char c;
struct Edge{
    int u,v,nxt;
}e[maxn * 2];
struct node{
    int l,r,num,tag,lc,rc;
}t[maxn * 4];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10  +  (c ^ 48),c = getchar();
    return x;
}
inline void insex(int x,int y){
    cnt ++,e[cnt].u = x,e[cnt].v = y,e[cnt].nxt = last[x],last[x] = cnt;
}
void dfs1(int u,int fa){
    size[u] = 1,f[u] = fa,d[u] = d[fa] + 1;
    for(int i = last[u]; i; i = e[i].nxt){
        int v = e[i].v;
        if(v == fa) continue;
        dfs1(v,u);
        size[u] += size[v];
        if(size[son[u]] < size[v]) son[u] = v;
    }
}
void dfs2(int u,int tp){
    pos[u] = ++tot,top[u] = tp;
    if(son[u]) dfs2(son[u],top[u]);
    for(int i = last[u]; i; i = e[i].nxt){
        int v = e[i].v;
        if(v != f[u] && v != son[u]) dfs2(v,v);
    }
}
inline int ls(int x){
    return x << 1;
}
inline int rs(int x){
    return x << 1 | 1;
}
void push_up(int x){
    t[x].lc = t[ls(x)].lc,t[x].rc = t[rs(x)].rc;
    t[x].num = t[ls(x)].num + t[rs(x)].num - (t[ls(x)].rc == t[rs(x)].lc);
}
void push_down(int x){
    if(!t[x].tag) return;
    t[ls(x)].tag = t[rs(x)].tag = t[x].tag;
    t[ls(x)].num = t[rs(x)].num = 1;
    t[ls(x)].lc = t[ls(x)].rc = t[x].lc;
    t[rs(x)].lc = t[rs(x)].rc = t[x].lc;
    t[x].tag = 0;
}
void build(int x,int l,int r){
    t[x].l = l,t[x].r = r;
    if(l == r) return;
    int mid = (l + r) / 2;
    build(ls(x),l,mid),build(rs(x),mid + 1,r);
}
void modify(int x,int l,int r,int k){
    if(t[x].l == l && t[x].r == r){
        t[x].num = t[x].tag = 1;
        t[x].lc = t[x].rc = k;
        return;
    }
    push_down(x);
    int mid = (t[x].l + t[x].r) / 2;
    if(r <= mid) modify(ls(x),l,r,k);
    else if(l > mid) modify(rs(x),l,r,k);
    else modify(ls(x),l,mid,k),modify(rs(x),mid + 1,r,k);
    push_up(x);
}
int sum(int L,int R,int x,int l,int r){
    if(t[x].l == L) Lc = t[x].lc;
    if(t[x].r == R) Rc = t[x].rc;
    if(t[x].l == l && t[x].r == r) return t[x].num;
    push_down(x);
    int mid = (t[x].l + t[x].r) / 2;
    if(r <= mid) return sum(L,R,ls(x),l,r);
    else if(l > mid) return sum(L,R,rs(x),l,r);
    else return sum(L,R,ls(x),l,mid) + sum(L,R,rs(x),mid + 1,r) - (t[ls(x)].rc == t[rs(x)].lc);
}
void update(int x,int y,int k){
    while(top[x] != top[y]){
        if(d[top[x]] < d[top[y]]) swap(x,y);
        modify(1,pos[top[x]],pos[x],k);
        x = f[top[x]];
    }
    if(d[x] > d[y]) swap(x,y);
    modify(1,pos[x],pos[y],k);
}
int query(int x,int y){
    int s = 0,s1 = -1,s2 = -1;
    while(top[x] != top[y]){
        if(d[top[x]] < d[top[y]]) swap(x,y),swap(s1,s2);
        s += sum(pos[top[x]],pos[x],1,pos[top[x]],pos[x]);
        if(Rc == s1) s--;
        s1 = Lc,x = f[top[x]];
    }
    if(d[x] < d[y]) swap(x,y),swap(s1,s2);
    s += sum(pos[y],pos[x],1,pos[y],pos[x]);
    if(Rc == s1) s--;
    if(Lc == s2) s--;
    return s;
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= n; i ++) a[i] = read();
    for(int i = 1; i < n; i ++){
        x = read(),y = read();
        insex(x,y),insex(y,x);
    }
    dfs1(1,1);
    dfs2(1,1);
    build(1,1,n);
    for(int i = 1; i <= n; i ++) modify(1,pos[i],pos[i],a[i]);
    while(m --){
        getchar();
        c = getchar();
        if(c == 'C'){
            x = read(),y = read(),k = read();
            update(x,y,k);
        }else{
            x = read(),y = read();
            printf("%d\n",query(x,y));
        }
    }
    return 0;
}
楼房重建: 线段树,玄妙的递归pushup
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1e5 + 50;
int n,m,x,y,ans[4 * maxn];
double num[maxn],mx[4 * maxn];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
inline int ls(int x){
    return x << 1;
}
inline int rs(int x){
    return x << 1 | 1;
}
int sum(int x,int l,int r,double k){
    if(l == r) return num[l] > k;
    if(num[l] > k) return ans[x];
    if(mx[x] <= k) return 0;
    int mid = (l + r) / 2;
    if(mx[ls(x)] > k) return ans[x] - ans[ls(x)] + sum(ls(x),l,mid,k);
    else return sum(rs(x),mid + 1,r,k);
}
inline void push_up(int x,int l,int r){
    mx[x] = max(mx[ls(x)],mx[rs(x)]),ans[x] = ans[ls(x)] + sum(rs(x),(l + r) / 2 + 1,r,mx[ls(x)]);
}
void update(int p,double k,int x,int l,int r){
    if(l == r){
        mx[x] = k,ans[x] = 1;
        return;
    }
    int mid = (l + r) / 2;
    if(p <= mid) update(p,k,ls(x),l,mid);
    else update(p,k,rs(x),mid + 1,r);
    push_up(x,l,r);
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= m; i ++){
        x = read(),y = read(),num[x] = 1.0 * y / x;
        update(x,1.0 * y / x,1,1,n);
        printf("%d\n",ans[1]);
    }
    return 0;
}
[NOI2016]区间: 线段树,尺取法,离散化
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 5e5 + 50,maxm = 8 * maxn,inf = 1e9;
int n,m,x,y,l,r,ans = inf,lb[maxn],rb[maxn],mx[maxm],tag[maxm];
struct node{
    int len,pos;
}a[maxn];
struct data{
    int num,pos;
}t[2 * maxn];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
bool cmp1(node x,node y){
    return x.len < y.len;
}
bool cmp2(data x,data y){
    return x.num < y.num;
}
inline int ls(int x){
    return x << 1;
}
inline int rs(int x){
    return x << 1 | 1;
}
inline void push_up(int x){
    mx[x] = max(mx[ls(x)],mx[rs(x)]);
}
void push_down(int x,int l,int r){
    mx[ls(x)] += tag[x],mx[rs(x)] += tag[x];
    tag[ls(x)] += tag[x],tag[rs(x)] += tag[x],tag[x] = 0;
}
void update(int L,int R,int k,int x,int l,int r){
    if(L <= l && R >= r){
        mx[x] += k,tag[x] += k;
        return;
    }
    push_down(x,l,r);
    int mid = (l + r) / 2;
    if(L <= mid) update(L,R,k,ls(x),l,mid);
    if(R > mid) update(L,R,k,rs(x),mid + 1,r);
    push_up(x);
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= n; i ++){
        x = read(),y = read();
        a[i].len = y - x,a[i].pos = i;
        t[2 * i - 1].num = x,t[2 * i - 1].pos = i,t[2 * i].num = y,t[2 * i].pos = i;
    }
    sort(a + 1,a + n + 1,cmp1);
    sort(t + 1,t + 2 * n + 1,cmp2);
    for(int i = 1; i <= 2 * n; i ++){
        int now = t[i].pos;
        if(!lb[now]) lb[now] = i;
        else rb[now] = i;
    }
    l = 0,r = 0;
    while(1){
        while(r < n && mx[1] < m) r ++,update(lb[a[r].pos],rb[a[r].pos],1,1,1,2 * n);
        if(mx[1] < m) break;
        while(l <= r && mx[1] >= m) l ++,update(lb[a[l].pos],rb[a[l].pos],-1,1,1,2 * n);
        ans = min(ans,a[r].len - a[l].len);
    }
    printf("%d\n",ans == inf ? -1 : ans);
    return 0;
}
后缀排序模板
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e6 + 50;
int n,mx,cnt,t[maxn],bk[maxn],x1[maxn],x2[maxn],sa[maxn];
char s[maxn];
void SA(){
    mx = 122;
    for(int i = 1; i <= n; i ++) x1[i] = s[i],bk[x1[i]] ++;
    for(int i = 1; i <= mx; i ++) bk[i] += bk[i - 1];
    for(int i = n; i >= 1; i --) sa[bk[x1[i]] --] = i;
    for(int k = 1; k <= n; k <<= 1){
        cnt = 0;
        for(int i = n - k + 1; i <= n; i ++) x2[++cnt] = i;
        for(int i = 1; i <= n; i ++) if(sa[i] > k) x2[++cnt] = sa[i] - k;
        for(int i = 1; i <= mx; i ++) bk[i] = 0;
        for(int i = 1; i <= n; i ++) bk[x1[i]] ++;
        for(int i = 1; i <= mx; i ++) bk[i] += bk[i - 1];
        for(int i = n; i >= 1; i --) sa[bk[x1[x2[i]]] --] = x2[i];
        for(int i = 1; i <= n; i ++) t[i] = x1[i];
        cnt = 0;
        for(int i = 1; i <= n; i ++){
            if(t[sa[i]] == t[sa[i - 1]] && t[sa[i] + k] == t[sa[i - 1] + k]) x1[sa[i]] = cnt;
            else x1[sa[i]] = ++cnt;
        }
        if(cnt == n) return;
        mx = cnt;
    }
}
int main(){
    scanf("%s",s + 1);
    n = strlen(s + 1);
    SA();
    for(int i = 1; i <= n; i ++) printf("%d ",sa[i]);
    printf("\n");
    return 0;
}
LCT模板
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1e5 + 50;
int n,m,x,y,type,top,num[maxn],s[maxn],r[maxn],fa[maxn],sta[maxn],son[maxn][2];
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
bool isroot(int u){
    return son[fa[u]][0] != u && son[fa[u]][1] != u;
}
void update(int u){
    s[u] = s[son[u][0]] ^ s[son[u][1]] ^ num[u];
}
void push_down(int u){
    if(r[u]){
        swap(son[u][0],son[u][1]);
        r[son[u][0]] ^= 1,r[son[u][1]] ^= 1;
        r[u] = 0;
    }
}
void rotate(int u){
    int v = fa[u],d = (son[v][1] == u);
    if(!isroot(v)) son[fa[v]][son[fa[v]][1] == v] = u;
    son[v][d] = son[u][d ^ 1],son[u][d ^ 1] = v;
    fa[u] = fa[v],fa[v] = u,fa[son[v][d]] = v;
    update(v),update(u);
}
void splay(int u){
    int t = u;
    sta[++top] = t;
    while(!isroot(t)) t = fa[t],sta[++top] = t;
    while(top) push_down(sta[top]),top --;
    while(!isroot(u)){
        int f = fa[u];
        if(isroot(f)){
            rotate(u);
            break;
        }
        if((son[fa[f]][1] == f) == (son[f][1] == u)) rotate(f),rotate(u);
        else rotate(u),rotate(u);
    }
}
void access(int u){
    int last = 0;
    while(u){
        splay(u);
        son[u][1] = last;
        update(u);
        last = u,u = fa[u];
    }
}
void change_root(int u){
    access(u);
    splay(u);
    r[u] ^= 1;
}
int root(int u){
    access(u);
    splay(u);
    push_down(u);
    while(son[u][0]) u = son[u][0],push_down(u);
    return u;
}
void split(int u,int v){
    change_root(u);
    access(v);
    splay(v);
}
void link(int u,int v){
    change_root(u);
    if(root(v) != u) fa[u] = v;
}
void cut(int u,int v){
    change_root(u);
    if(root(v) == u && fa[u] == v && son[v][0] == u && !son[u][1]){
        fa[u] = 0,son[v][0] = 0;
        update(v);
    }
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= n; i ++) num[i] = read();
    for(int i = 1; i <= m; i ++){
        type = read(),x = read(),y = read();
        if(type == 0){
            split(x,y);
            printf("%d\n",s[y]);
        }else if(type == 1) link(x,y);
        else if(type == 2) cut(x,y);
        else{
            splay(x);
            num[x] = y;
            update(x);
        }
    }
}
[国家集训队]Tree II: LCT,lazy tag
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 1e5 + 50,mod = 51061;
int n,m,x,y,k,top,size[maxn],fa[maxn],son[maxn][2],r[maxn],sta[maxn];
long long s[maxn],num[maxn],add[maxn],mul[maxn];
char type;
int read(){
    int x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = x * 10 + (c ^ 48),c = getchar();
    return x;
}
bool nroot(int u){
    return son[fa[u]][0] == u || son[fa[u]][1] == u;
}
void update(int u){
    size[u] = size[son[u][0]] + size[son[u][1]] + 1;
    s[u] = (s[son[u][0]] + s[son[u][1]] + num[u]) % mod;
}
void update_mul(int u,int k){
    num[u] = num[u] * k % mod;
    s[u] = s[u] * k % mod;
    add[u] = add[u] * k % mod;
    mul[u] = mul[u] * k % mod;
}
void update_add(int u,int k){
    num[u] = (num[u] + k) % mod;
    s[u] = (s[u] + 1ll * k * size[u]) % mod;
    add[u] = (add[u] + k) % mod;
}
void push_down(int u){
    update_mul(son[u][0],mul[u]),update_mul(son[u][1],mul[u]);
    update_add(son[u][0],add[u]),update_add(son[u][1],add[u]);
    if(r[u]){
        swap(son[u][0],son[u][1]);
        r[son[u][0]] ^= 1,r[son[u][1]] ^= 1;
        r[u] = 0;
    }
    add[u] = 0,mul[u] = 1;
    update(u);
}
void rotate(int u){
    int v = fa[u],d = (son[v][1] == u);
    if(nroot(v)) son[fa[v]][son[fa[v]][1] == v] = u;
    son[v][d] = son[u][d ^ 1],son[u][d ^ 1] = v;
    fa[u] = fa[v],fa[v] = u,fa[son[v][d]] = v;
    update(v),update(u);
}
void splay(int u){
    int t = u;
    sta[++top] = t;
    while(nroot(t)) t = fa[t],sta[++top] = t;
    while(top) push_down(sta[top]),top --;
    while(nroot(u)){
        int f = fa[u];
        if(!nroot(f)){
            rotate(u);
            break;
        }
        if((son[fa[f]][0] == f) == (son[f][0] == u)) rotate(f),rotate(u);
        else rotate(u),rotate(u);
    }
}
void access(int u){
    int last = 0;
    while(u){
        splay(u);
        son[u][1] = last;
        update(u);
        last = u,u = fa[u];
    }
}
void change_root(int u){
    access(u);
    splay(u);
    r[u] ^= 1;
}
int root(int u){
    access(u);
    splay(u);
    while(son[u][0]) push_down(u),u = son[u][0];
    return u;
}
void split(int u,int v){
    change_root(u);
    access(v);
    splay(v);
}
void link(int u,int v){
    change_root(u);
    access(v);
    splay(v);
    fa[u] = v;
}
void cut(int u,int v){
    split(u,v);
    fa[u] = 0,son[v][0] = 0;
}
int main(){
    n = read(),m = read();
    for(int i = 1; i <= n; i ++) num[i] = 1,size[i] = 1,mul[i] = 1;
    for(int i = 1; i < n; i ++){
        x = read(),y = read();
        link(x,y);
    }
    for(int i = 1; i <= m; i ++){
        type = getchar();
        if(type == '+'){
            x = read(),y = read(),k = read();
            split(x,y);
            update_add(y,k);
        }else if(type == '-'){
            x = read(),y = read();
            cut(x,y);
            x = read(),y = read();
            link(x,y);
        }else if(type == '*'){
            x = read(),y = read(),k = read();
            split(x,y);
            update_mul(y,k);
        }else{
            x = read(),y = read();
            split(x,y);
            printf("%lld\n",s[y]);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值