zoukankan      html  css  js  c++  java
  • 数据结构

    void init()
    {
        for(int i = 1;i <= n;i++)    pre[i] = i;
    } 
    
    int findd(int x)       递归     
    {
        return pre[x] == x?x:pre[x] = findd(pre[x]);
    }
    
    void join(int a,int b)
    {
        int x = findd(a),y = findd(b);
        if(x != y)  pre[x] = y;
    }    
    并查集
    #include <stdio.h>
    const int N = 50005;
    int pre[N],rk[N];
    /*
        解题思路:father[y] = x
        如果rank[y]为0 代表x 和 y属于同一种
        如果rank[y]为1 代表x 吃 y
        如果rank[y]为2 代表y 吃 x
        本题的关键就是如何在路径压缩的过程中更新关系权值
        需要总结更新公式
    */
    int findd(int x)
    {
        if(pre[x] == x) return x;
        int xx = findd(pre[x]);
        rk[x] = (rk[x]+rk[pre[x]])%3;
        pre[x] = xx;
        return xx;
    }
    bool ok(int n,int type,int x,int y)
    {
        if(x > n || y > n)  return 0;
        int fx = findd(x),fy = findd(y);
        if(fx == fy)
        {
            if((rk[y]-rk[x]+3)%3 != type-1) return 0;
            return 1;
        }
        else
        {
            pre[fy] = fx;
            rk[fy] = (rk[x]-rk[y]+type-1+3)%3;
            return 1;
        }
    }
    
    int main()
    {
        int n,k;
        scanf("%d %d",&n,&k);
        for(int i = 1;i <= n;i++)
        {
            pre[i] = i;
            rk[i] = 0;
        }
        int cnt = 0;
        for(int i = 0;i < k;i++)
        {
            int d,x,y;
            scanf("%d %d %d",&d,&x,&y);
            if(!ok(n,d,x,y))    cnt++;
        }
        printf("%d
    ",cnt);
        return 0;
    }
    带权值并查集

    struct ST
    {
        int mm[100005],dp[100005][20];
        void init()
        {
            mm[0] = -1;
            for(int i = 1;i <= n;i++)
            {
                mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
                dp[i][0] = a[i];
            }
            for(int j = 1;j <= mm[n];j++)
            {
                for(int i = 1;i+(1<<j)-1 <= n;i++)  dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
            }
        }
        int query(int a,int b)
        {
            if(a > b)   swap(a,b);
            int k = mm[b-a+1];
            return min(dp[a][k],dp[b-(1<<k)+1][k]);
        }
    }st;
    一维rmq
    //同一维一样 用dp[row][col][i][j]表示(row,col)到(row+2^i,col+2^j)矩形内的最小值
    int a[305][305],mm[305],dp[305][305][9][9];
    
    void init(int n,int m)
    {
        for(int i = 1;i <= 300;i++) mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
        for(int i = 1;i <= n;i++)
        {
            for(int j = 1;j <= m;j++)   dp[i][j][0][0] = a[i][j];
        }
        for(int i = 0;i <= mm[n];i++)
        {
            for(int j = 0;j <= mm[m];j++)
            {
                if(i==0 && j==0)    continue;
                for(int row = 1;row+(1<<i)-1 <= n;row++)
                {
                    for(int col = 1;col+(1<<j)-1 <= m;col++)
                    {
                        if(i)   dp[row][col][i][j]  = max(dp[row][col][i-1][j],dp[row+(1<<(i-1))][col][i-1][j]);
                        else    dp[row][col][i][j]  = max(dp[row][col][i][j-1],dp[row][col+(1<<(j-1))][i][j-1]);
                    }
                }
            }
        }
    }
    int rmq(int x1,int y1,int x2,int y2)
    {
        int k1 = mm[x2-x1+1],k2 = mm[y2-y1+1];
        x2 = x2-(1<<k1)+1,y2 = y2-(1<<k2)+1;
        return max(max(dp[x1][y1][k1][k2],dp[x1][y2][k1][k2]),max(dp[x2][y1][k1][k2],dp[x2][y2][k1][k2]));
    }
    二维rmq

    #include<bits/stdc++.h>
    using namespace std;
    
    stack<long long> s;
    long long a[100005];
    int main()
    {
        int n;
        while(scanf("%d",&n) && n)
        {
            while(!s.empty())   s.pop();
            long long ans = 0;
            for(int i = 1;i <= n;i++)   scanf("%lld",&a[i]);
            a[n+1] = 0;
            for(int i = 1;i <= n+1;i++)
            {
                while(!s.empty() && a[s.top()] > a[i])
                {
                    int temp = s.top();
                    s.pop();
                    int len = s.empty()?i-1:i-s.top()-1;
                    ans = max(ans,len*a[temp]);
                }
                s.push(i);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    //HDU1506
    单调栈
    #include<bits/stdc++.h>
    using namespace std;
    
    struct st
    {
        int num,t;
    }s;
    deque<st> q;
    int n,x;
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            while(!q.empty())   q.pop_back();
            int out = 1,cnt = 1;
            for(int i = 1;i <= n;i++)
            {
                scanf("%d",&x);
                switch(x)
                {
                    case 1:
                        int tt;
                        scanf("%d",&tt);
                        s.t = tt-i;
                        s.num = cnt++;
                        while(!q.empty() && q.back().t <= s.t)    q.pop_back();
                        q.push_back(s);
                        break;
                    case 2:
                        if(q.front().num == out++)  q.pop_front();
                        break;
                    case 3:
                        printf("%d
    ",q.front().t+i);
                }
            }
        }
        return 0;
    }
    
    //XDOJ1156
    单调队列

    int tree[50005],n;
    
    inline int lowbit(int x)
    {
        return x & (-x);
    }
    
    void update(int pos,int x)
    {
        while(pos <= n)
        {
            tree[pos] += x;
            pos += lowbit(pos);
        }
    }
    
    int getsum(int pos)
    {
        int sum = 0;
        while(pos > 0)
        {
            sum += tree[pos];
            pos -= lowbit(pos);
        }
        return sum;
    }
    一维树状数组
    int tree[1005][1005] = {0},a[1005][1005] = {0};
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void update(int x,int y,int w)
    {
        for(int i = x;i <= 1001;i += lowbit(i))
        {
            for(int j = y;j <= 1001;j += lowbit(j)) tree[i][j] += w;
        }
    }
    
    int getsum(int x,int y)
    {
        int ans = 0;
        for(int i = x;i > 0;i -= lowbit(i))
        {
            for(int j = y;j > 0;j -= lowbit(j)) ans += tree[i][j];
        }
        return ans;
    }
    二维树状数组

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100005
    
    int n,m,tree[20][N],sorted[N],toleft[20][N];
    
    void build(int l,int r,int dep)
    {
        if(l == r)return;
        int mid = (l+r)/2,same = mid-l+1;
        for(int i = l;i <= r;i++)
        {
            if(tree[dep][i] < sorted[mid])  same--;
        }
        int lpos = l,rpos = mid+1;
        for(int i = l;i <= r;i++)
        {
            if(tree[dep][i] < sorted[mid])  tree[dep+1][lpos++] = tree[dep][i];
            else if(tree[dep][i] == sorted[mid] && same > 0)
            {
                tree[dep+1][lpos++] = tree[dep][i];
                same--;
            }
            else    tree[dep+1][rpos++] = tree[dep][i];
            toleft[dep][i] = toleft[dep][l-1]+lpos-l;
        }
        build(l,mid,dep+1);
        build(mid+1,r,dep+1);
    }
    
    int query(int l,int r,int ql,int qr,int dep,int k)
    {
        if(ql == qr)    return tree[dep][ql];
        int mid = (l+r)/2,cnt = toleft[dep][qr]-toleft[dep][ql-1];
        if(cnt >= k)
        {
            int ll = l+toleft[dep][ql-1]-toleft[dep][l-1],rr = ll+cnt-1;
            return query(l,mid,ll,rr,dep+1,k);
        }
        else
        {
            int rr = qr+toleft[dep][r]-toleft[dep][qr],ll = rr-(qr-ql-cnt);
            return query(mid+1,r,ll,rr,dep+1,k-cnt);
        }
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i = 1;i <= n;i++)
            {
                scanf("%d",&tree[0][i]);
                sorted[i] = tree[0][i];
            }
            sort(sorted+1,sorted+n+1);
            build(1,n,0);
            while(m--)
            {
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",query(1,n,l,r,0,k));
            }
        }
        return 0;
    }
    划分树查询区间第k大

    int n,k,root,son[10005],vis[10005],minn,ans,sum,dis[10005],dep[10005];
    struct xx
    {
        int to,w;
        xx(int a,int b):to(a),w(b){};
    };
    vector<xx> v[10005];
    
    void dfsroot(int now,int pre)
    {
        son[now] = 1;
        int maxx = 0;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i].to,w = v[now][i].w;
            if(t == pre || vis[t])  continue;
            dfsroot(t,now);
            son[now] += son[t];
            maxx = max(maxx,son[t]);
        }
        maxx = max(maxx,sum-son[now]);
        if(maxx < minn)
        {
            minn = maxx;
            root = now;
        }
    }
    
    void dfsdep(int now,int pre)
    {
        dep[++dep[0]] = dis[now];
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i].to,w = v[now][i].w;
            if(t == pre || vis[t])  continue;
            dis[t] = dis[now]+w;
            dfsdep(t,now);
        }
    }
    
    int calc(int now,int w)
    {
        dis[now] = w;
        dep[0] = 0;
        dfsdep(now,0);
        sort(dep+1,dep+dep[0]+1);
        int l = 1,r = dep[0],cnt = 0;
        while(l < r)
        {
            if(dep[l]+dep[r] <= k)
            {
                cnt += r-l;
                l++;
            }
            else    r--;
        }
        return cnt;
    }
    
    void solve(int now)
    {
        ans += calc(now,0);
        vis[now] = 1;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i].to,w = v[now][i].w;
            if(vis[t])  continue;
            ans -= calc(t,w);
            minn = 1e9;
            sum = son[t];
            dfsroot(t,0);
            solve(root);
        }
    }
    
    int main()
    {
        while(scanf("%d%d",&n,&k))
        {
            if(n == 0 || k == 0)    break;
            ans = 0,sum = n;
            memset(vis,0,sizeof(vis));
            for(int i = 1;i <= n;i++)   v[i].clear();
            for(int i = 1;i < n;i++)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                v[x].push_back(xx(y,z));
                v[y].push_back(xx(x,z));
            }
            minn = 1e9;
            dfsroot(1,0);
            solve(root);
            printf("%d
    ",ans);
        }
        return 0;
    }
    点分治求边权和等于k的数量
    int n,k,root,son[100005],vis[100005],dep[100005],id[1000005],minn,ans1,ans2,sum;
    long long a[100005],inv[1000005],mp[1000005];
    vector<int> v[100005];
    
    void dfsroot(int now,int pre)
    {
        son[now] = 1;
        int maxx = 0;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t == pre || vis[t])  continue;
            dfsroot(t,now);
            son[now] += son[t];
            maxx = max(maxx,son[t]);
        }
        maxx = max(maxx,sum-son[now]);
        if(maxx < minn)
        {
            minn = maxx;
            root = now;
        }
    }
    
    void dfsdep(int now,int pre,long long x)
    {
        dep[++dep[0]] = x*a[now]%MOD;
        id[dep[0]] = now;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t == pre || vis[t])  continue;
            dfsdep(t,now,x*a[now]%MOD);
        }
    }
    
    void update(int now,int x,int y)
    {
        int t = mp[inv[x*a[now]%MOD]*k%MOD];
        if(!t)  return;
        if(t > y)   swap(t,y);
        if(t < ans1 || t == ans1 && y < ans2)
        {
            ans1 = t;
            ans2 = y;
        }
    }
    
    void solve(int now)
    {
        vis[now] = 1;
        mp[1] = now;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(vis[t])  continue;
            dep[0] = 0;
            dfsdep(t,now,1);
            for(int j = 1;j <= dep[0];j++)  update(now,dep[j],id[j]);
            for(int j = 1;j <= dep[0];j++)
            {
                if(!mp[dep[j]] || mp[dep[j]] > id[j])   mp[dep[j]] = id[j];
            }
        }
        mp[1] = 0;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(vis[t])  continue;
            dep[0] = 0;
            dfsdep(t,now,1);
            for(int j = 1;j <= dep[0];j++)  mp[dep[j]] = 0;
        }
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(vis[t])  continue;
            minn = 1e9;
            sum = son[t];
            dfsroot(t,0);
            solve(root);
        }
    }
    
    int main()
    {
        inv[1] = 1;
        for(int i = 2;i < MOD;i++)  inv[i] = (MOD-MOD/i)*inv[MOD%i]%MOD;
        while(~scanf("%d%d",&n,&k))
        {
            ans1 = 1e9,ans2 = 0;
            memset(vis,0,sizeof(vis));
            for(int i = 1;i <= n;i++)   v[i].clear();
            for(int i = 1;i <= n;i++)   scanf("%lld",&a[i]);
            for(int i = 1;i < n;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                v[x].push_back(y);
                v[y].push_back(x);
            }
            minn = 1e9;
            sum = n;
            dfsroot(1,0);
            solve(root);
            if(ans1 == 1e9) printf("No solution
    ");
            else    printf("%d %d
    ",ans1,ans2);
        }
        return 0;
    }
    点分治求点权积等于k

    int n,maxx,tree[100005],ans[100005];
    struct xx
    {
        int x,y,z,id;
        xx(int a,int b,int c,int d):x(a),y(b),z(c),id(d){};
        xx(){};
    }a[100005],b[100005];
    
    inline lowbit(int x)
    {
        return x&-x;
    }
    
    void add(int pos,int x)
    {
        while(pos <= maxx)
        {
            tree[pos] += x;
            pos += lowbit(pos);
        }
    }
    
    int getsum(int pos)
    {
        int ans = 0;
        while(pos > 0)
        {
            ans += tree[pos];
            pos -= lowbit(pos);
        }
        return ans;
    }
    
    bool cmp1(xx a,xx b)
    {
        if(a.x != b.x)  return a.x < b.x;
        if(a.y != b.y)  return a.y < b.y;
        return a.z < b.z;
    }
    
    bool cmp2(xx a,xx b)
    {
        if(a.y != b.y)  return a.y < b.y;
        return a.id < b.id;
    }
    
    void cdq(int l,int r)
    {
        if(l == r)  return;
        int mid = (l+r)/2;
        int cnt = 0;
        for(int i = l;i <= mid;i++) b[++cnt] = xx(0,a[i].y,a[i].z,0);
        for(int i = mid+1;i <= r;i++)   b[++cnt] = xx(0,a[i].y,a[i].z,a[i].id);
        sort(b+1,b+1+cnt,cmp2);
        for(int i = 1;i <= cnt;i++)
        {
            if(b[i].id == 0)    add(b[i].z,1);
            else    ans[b[i].id] += getsum(b[i].z);
        }
        for(int i = 1;i <= cnt;i++)
        {
            if(b[i].id == 0)    add(b[i].z,-1);
        }
        cdq(l,mid);
        cdq(mid+1,r);
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            maxx = 0;
            for(int i = 1;i <= n;i++)
            {
                scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
                a[i].id = i;
                maxx = max(maxx,a[i].z);
            }
            sort(a+1,a+1+n,cmp1);
            memset(ans,0,sizeof(ans));
            int cnt = 0;
            for(int i = n-1;i >= 1;i--)
            {
                if(a[i].x == a[i+1].x && a[i].y == a[i+1].y && a[i].z == a[i+1].z)  cnt++;
                else    cnt = 0;
                ans[a[i].id] += cnt;
            }
            cdq(1,n);
            for(int i = 1;i <= n;i++)   printf("%d
    ",ans[i]);
        }
        return 0;
    }
    cdq分治求三维偏序

    //点权,修改路径点权,查询单点权
    #include<bits/stdc++.h>
    using namespace std;
    #define N 50005
    int n,m,q,cnt,a[N],top[N],fa[N],dep[N],num[N],p[N],fp[N],son[N];
    vector<int> v[N];
    char s[10];
    
    struct segtree
    {
        int l,r;
        long long x,lazy;
    }tree[4*N];
    
    inline void pushup(int pos)
    {
        tree[pos].x = tree[pos<<1].x+tree[pos<<1|1].x;
    }
    
    inline void pushdown(int pos)
    {
        if(tree[pos].lazy)
        {
            tree[pos<<1].x += (tree[pos<<1].r-tree[pos<<1].l+1)*tree[pos].lazy;
            tree[pos<<1|1].x += (tree[pos<<1|1].r-tree[pos<<1|1].l+1)*tree[pos].lazy;
            tree[pos<<1].lazy += tree[pos].lazy;
            tree[pos<<1|1].lazy += tree[pos].lazy;
            tree[pos].lazy = 0;
        }
    }
    
    void build(int pos,int l,int r)
    {
        tree[pos].l = l;
        tree[pos].r = r;
        tree[pos].lazy = 0;
        if(l == r)
        {
            tree[pos].x = a[fp[l]];
            return;
        }
        int mid = (l+r)/2;
        build(pos<<1,l,mid);
        build(pos<<1|1,mid+1,r);
        pushup(pos);
    }
    
    void update(int pos,int l,int r,long long x)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return;
        if(l <= tree[pos].l && tree[pos].r <= r)
        {
            tree[pos].x += (tree[pos].r-tree[pos].l+1)*x;
            tree[pos].lazy += x;
            return;
        }
        pushdown(pos);
        update(pos<<1,l,r,x);
        update(pos<<1|1,l,r,x);
        pushup(pos);
    }
    
    long long getsum(int pos,int l,int r)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return 0;
        if(l <= tree[pos].l && tree[pos].r <= r)    return tree[pos].x;
        pushdown(pos);
        return  getsum(pos<<1,l,r)+getsum(pos<<1|1,l,r);
    }
    
    void dfs(int now,int pre,int d)
    {
        dep[now] = d;
        fa[now] = pre;
        num[now] = 1;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t == pre)    continue;
            dfs(t,now,d+1);
            num[now] += num[t];
            if(son[now] == -1 || num[t] > num[son[now]])    son[now] = t;
        }
    }
    
    void getpos(int now,int sp)
    {
        top[now] = sp;
        p[now] = ++cnt;
        fp[p[now]] = now;
        if(son[now] == -1)  return;
        getpos(son[now],sp);
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t != son[now] && t != fa[now])   getpos(t,t);
        }
    }
    
    void change(int u,int v,int x)
    {
        int f1 = top[u],f2 = top[v];
        while(f1 != f2)
        {
            if(dep[f1] < dep[f2])
            {
                swap(f1,f2);
                swap(u,v);
            }
            update(1,p[f1],p[u],x);
            u = fa[f1];
            f1 = top[u];
        }
        if(dep[u] > dep[v]) swap(u,v);
        update(1,p[u],p[v],x);
    }
    
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&q))
        {
            memset(son,-1,sizeof(son));
            memset(tree,0,sizeof(tree));
            for(int i = 1;i <= n;i++)   v[i].clear();
            cnt = 0;
            for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
            while(m--)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                v[x].push_back(y);
                v[y].push_back(x);
            }
            dfs(1,0,0);
            getpos(1,1);
            build(1,1,cnt);
            while(q--)
            {
                scanf("%s",s);
                if(s[0] == 'Q')
                {
                    int x;
                    scanf("%d",&x);
                    printf("%lld
    ",getsum(1,p[x],p[x]));
                }
                else
                {
                    int x,y,z;
                    scanf("%d%d%d",&x,&y,&z);
                    if(s[0] == 'D')    z = -z;
                    change(x,y,z);
                }
            }
        }
        return 0;
    }
    树链剖分线段树(点权)
    #include<bits/stdc++.h>
    #define N 10005
    using namespace std;
    
    int n,m,q,cnt,a[N],val[N],top[N],fa[N],dep[N],num[N],p[N],fp[N],son[N],e[N][3];
    struct segtree
    {
        int l,r,x;
    }tree[4*N];
    vector<int> v[N];
    char s[10];
    
    void pushup(int pos)
    {
        tree[pos].x = max(tree[pos<<1].x,tree[pos<<1|1].x);
    }
    
    void build(int pos,int l,int r)
    {
        tree[pos].l = l;
        tree[pos].r = r;
        if(l == r)
        {
            tree[pos].x = val[l];
            return;
        }
        int mid = (l+r)/2;
        build(pos<<1,l,mid);
        build(pos<<1|1,mid+1,r);
        pushup(pos);
    }
    
    void update(int pos,int l,int r,int x)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return;
        if(l <= tree[pos].l && tree[pos].r <= r)
        {
            tree[pos].x = x;
            return;
        }
        update(pos<<1,l,r,x);
        update(pos<<1|1,l,r,x);
        pushup(pos);
    }
    
    int query(int pos,int l,int r)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return 0;
        if(l <= tree[pos].l && tree[pos].r <= r)    return tree[pos].x;
        return  max(query(pos<<1,l,r),query(pos<<1|1,l,r));
    }
    
    void dfs(int now,int pre,int d)
    {
        dep[now] = d;
        fa[now] = pre;
        num[now] = 1;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t == pre)    continue;
            dfs(t,now,d+1);
            num[now] += num[t];
            if(son[now] == -1 || num[t] > num[son[now]])    son[now] = t;
        }
    }
    
    void getpos(int now,int sp)
    {
        top[now] = sp;
        p[now] = ++cnt;
        fp[p[now]] = now;
        if(son[now] == -1)  return;
        getpos(son[now],sp);
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t != son[now] && t != fa[now])   getpos(t,t);
        }
    }
    
    int solve(int u,int v)
    {
        int f1 = top[u],f2 = top[v],t = 0;
        while(f1 != f2)
        {
            if(dep[f1] < dep[f2])
            {
                swap(f1,f2);
                swap(u,v);
            }
            t = max(t,query(1,p[f1],p[u]));
            u = fa[f1];
            f1 = top[u];
        }
        if(u == v)  return t;
        if(dep[u] > dep[v]) swap(u,v);
        return max(t,query(1,p[son[u]],p[v]));
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            memset(son,-1,sizeof(son));
            for(int i = 1;i <= n;i++)   v[i].clear();
            cnt = 0;
            for(int i = 1;i < n;i++)
            {
                scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
                v[e[i][0]].push_back(e[i][1]);
                v[e[i][1]].push_back(e[i][0]);
            }
            dfs(1,0,0);
            getpos(1,1);
            for(int i = 1;i < n;i++)
            {
                if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0],e[i][1]);
                val[p[e[i][1]]] = e[i][2];
            }
            build(1,1,cnt);
            while(scanf("%s",s))
            {
                if(s[0] == 'D') break;
                int x,y;
                scanf("%d%d",&x,&y);
                if(s[0] == 'Q') printf("%d
    ",solve(x,y));
                else    update(1,p[e[x][1]],p[e[x][1]],y);
            }
        }
        return 0;
    }
    树链剖分线段树(边权)

    struct segtree
    {
        int l,r;
        long long x,lazy;
    }tree[400005];
    
    inline void pushup(int pos)
    {
        tree[pos].x = tree[pos<<1].x+tree[pos<<1|1].x;
    }
    
    inline void pushdown(int pos)
    {
        if(tree[pos].lazy)
        {
            tree[pos<<1].x += (tree[pos<<1].r-tree[pos<<1].l+1)*tree[pos].lazy;
            tree[pos<<1|1].x += (tree[pos<<1|1].r-tree[pos<<1|1].l+1)*tree[pos].lazy;
            tree[pos<<1].lazy += tree[pos].lazy;
            tree[pos<<1|1].lazy += tree[pos].lazy;    
            tree[pos].lazy = 0;
        }
    }
    
    void build(int pos,int l,int r)   
    {
        tree[pos].l = l;
        tree[pos].r = r;
        tree[pos].lazy = 0;
        if(l == r)
        {
            tree[pos].x = a[l];
            return;
        }
        int mid = (l+r)/2;
        build(pos<<1,l,mid);
        build(pos<<1|1,mid+1,r);
        pushup(pos);
    }
    
    void update(int pos,int l,int r,long long x)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return;
        if(l <= tree[pos].l && tree[pos].r <= r)
        {
            tree[pos].x = (tree[pos].r-tree[pos].l+1)*x;
            tree[pos].lazy = x;
            return;
        }
        pushdown(pos);
        update(pos<<1,l,r,x);
        update(pos<<1|1,l,r,x);
        pushup(pos);
    }
    
    long long getsum(int pos,int l,int r)    
    {
        if(r < tree[pos].l || tree[pos].r < l)  return 0;
        if(l <= tree[pos].l && tree[pos].r <= r)    return tree[pos].x;
        pushdown(pos);
        return  getsum(pos<<1,l,r)+getsum(pos<<1|1,l,r);
    }
    线段树模版
    int n,k,q,cnt = 0,a[100005];
    struct segtree
    {
        int l,r,x,lazy;
        segtree *lson,*rson;
    }*root;
    
    segtree *newnode(int l,int r)
    {
        segtree *t = new segtree;
        t->l = l;
        t->r = r;
        t->lson = NULL;
        t->rson = NULL;
        t->lazy = 0;
        t->x = a[l];
        return t;
    }
    
    segtree *newlson(segtree *pos)
    {
        int mid = (pos->l+pos->r)/2;
        return newnode(pos->l,mid);
    }
    
    segtree *newrson(segtree *pos)
    {
        int mid = (pos->l+pos->r)/2;
        return newnode(mid+1,pos->r);
    }
    
    void pushup(segtree *pos)
    {
        if(!pos->lson)  pos->lson = newlson(pos);
        if(!pos->rson)  pos->rson = newrson(pos);
        pos->x = min(pos->lson->x,pos->rson->x);
    }
    
    void pushdown(segtree *pos)
    {
        if(!pos->lson)  pos->lson = newlson(pos);
        if(!pos->rson)  pos->rson = newrson(pos);
        if(pos->lazy)
        {
            pos->lson->x = pos->lazy;
            pos->rson->x = pos->lazy;
            pos->lson->lazy = pos->lazy;
            pos->rson->lazy = pos->lazy;
            pos->lazy = 0;
        }
    }
    
    void update(segtree *pos,int l,int r,int x)
    {
        if(r < pos->l || pos->r < l)    return;
        if(l <= pos->l && pos->r <= r)
        {
            pos->x = x;
            pos->lazy = x;
            return;
        }
        pushdown(pos);
        update(pos->lson,l,r,x);
        update(pos->rson,l,r,x);
        pushup(pos);
    }
    
    int getmin(segtree *pos,int l,int r)
    {
        if(r < pos->l || pos->r < l)    return 1e9;
        if(l <= pos->l && pos->r <= r)  return pos->x;
        pushdown(pos);
        return min(getmin(pos->lson,l,r),getmin(pos->rson,l,r));
    }
    动态开点线段树
    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m;
    long long a[100005];
    struct segtree
    {
        int l,r;
        long long x,sum;
    }tree[400005];
    
    
    inline void pushup(int pos)
    {
        tree[pos].x = max(tree[pos<<1].x,tree[pos<<1|1].x);
        tree[pos].sum = tree[pos<<1].sum+tree[pos<<1|1].sum;
    }
    
    void build(int pos,int l,int r)
    {
        tree[pos].l = l;
        tree[pos].r = r;
        if(l >= r)
        {
            tree[pos].x = a[l];
            tree[pos].sum = a[l];
            return;
        }
        int mid = (l+r)/2;
        build(pos<<1,l,mid);
        build(pos<<1|1,mid+1,r);
        pushup(pos);
    }
    
    void edit(int pos,int l,int r,long long x,int t)
    {
        if(t < l || t > r)  return;
        if(l == r)
        {
            tree[pos].x = x;
            tree[pos].sum = x;
            return;
        }
        int mid = (l+r)/2;
        edit(pos<<1,l,mid,x,t);
        edit(pos<<1|1,mid+1,r,x,t);
        pushup(pos);
    }
    
    void mod(int pos,int l,int r,long long x)
    {
        if(r < tree[pos].l || tree[pos].r < l || tree[pos].x < x)   return;
        if(tree[pos].l == tree[pos].r)
        {
            tree[pos].x %= x;
            tree[pos].sum = tree[pos].x;
            return;
        }
        mod(pos<<1,l,r,x);
        mod(pos<<1|1,l,r,x);
        pushup(pos);
    }
    
    long long getsum(int pos,int l,int r)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return 0;
        if(l <= tree[pos].l && tree[pos].r <= r)    return tree[pos].sum;
        return  getsum(pos<<1,l,r)+getsum(pos<<1|1,l,r);
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> m;
        for(int i = 1;i <= n;i++)   cin >> a[i];
        build(1,1,n);
        for(int i = 1;i <= m;i++)
        {
            int z,l,r,x;
            cin >> z;
            if(z == 1)
            {
                cin >> l >> r;
                cout << getsum(1,l,r) << endl;
            }
            else if(z == 2)
            {
                cin >> l >> r >> x;
                mod(1,l,r,x);
            }
            else
            {
                cin >> l >> x;
                edit(1,1,n,x,l);
            }
        }
        return 0;
    }
    //CF438D
    区间取模,单点修改,询问区间和
    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m;
    long long a[100005];
    struct segtree
    {
        int l,r;
        long long ma,mi,sum,lazy;
    }tree[400005];
    
    
    inline void pushup(int pos)
    {
        tree[pos].ma = max(tree[pos<<1].ma,tree[pos<<1|1].ma);
        tree[pos].mi = min(tree[pos<<1].mi,tree[pos<<1|1].mi);
        tree[pos].sum = tree[pos<<1].sum+tree[pos<<1|1].sum;
    }
    
    inline void pushdown(int pos)
    {
        if(tree[pos].lazy)
        {
            long long t = tree[pos].lazy;
            tree[pos<<1].lazy += t;
            tree[pos<<1|1].lazy += t;
            tree[pos<<1].mi += t;
            tree[pos<<1|1].mi += t;
            tree[pos<<1].ma += t;
            tree[pos<<1|1].ma += t;
            tree[pos<<1].sum += (tree[pos<<1].r-tree[pos<<1].l+1)*t;
            tree[pos<<1|1].sum += (tree[pos<<1|1].r-tree[pos<<1|1].l+1)*t;
            tree[pos].lazy = 0;
        }
    }
    
    void build(int pos,int l,int r)
    {
        tree[pos].l = l;
        tree[pos].r = r;
        tree[pos].lazy = 0;
        if(l == r)
        {
            tree[pos].mi = a[l];
            tree[pos].ma = a[l];
            tree[pos].sum = a[l];
            return;
        }
        int mid = (l+r)/2;
        build(pos<<1,l,mid);
        build(pos<<1|1,mid+1,r);
        pushup(pos);
    }
    
    long long getsum(int pos,int l,int r)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return 0;
        if(l <= tree[pos].l && tree[pos].r <= r)    return tree[pos].sum;
        pushdown(pos);
        return  getsum(pos<<1,l,r)+getsum(pos<<1|1,l,r);
    }
    
    void update(int pos,int l,int r,long long x)
    {
        if(r < tree[pos].l || tree[pos].r < l)    return;
        if(l <= tree[pos].l && tree[pos].r <= r)
        {
            tree[pos].mi += x;
            tree[pos].ma += x;
            tree[pos].sum += (tree[pos].r-tree[pos].l+1)*x;
            tree[pos].lazy += x;
            return;
        }
        pushdown(pos);
        update(pos<<1,l,r,x);
        update(pos<<1|1,l,r,x);
        pushup(pos);
    }
    
    void sq(int pos,int l,int r)
    {
        if(r < tree[pos].l || tree[pos].r < l)    return;
        if(l <= tree[pos].l && tree[pos].r <= r && (long long)sqrt(tree[pos].ma)-(long long)sqrt(tree[pos].mi) == tree[pos].ma-tree[pos].mi)
        {
            long long t = tree[pos].ma-(long long)sqrt(tree[pos].ma);
            tree[pos].mi -= t;
            tree[pos].ma -= t;
            tree[pos].sum -= (tree[pos].r-tree[pos].l+1)*t;
            tree[pos].lazy -= t;
            return;
        }
        pushdown(pos);
        sq(pos<<1,l,r);
        sq(pos<<1|1,l,r);
        pushup(pos);
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        cin >> n >> m;
        for(int i = 1;i <= n;i++)   cin >> a[i];
        build(1,1,n);
        for(int i = 1;i <= m;i++)
        {
            int z,l,r,x;
            cin >> z >> l >> r;
            if(z == 1)
            {
                cin >> x;
                update(1,l,r,x);
            }
            else if(z == 2) sq(1,l,r);
            else    cout << getsum(1,l,r) << endl;
        }
        return 0;
    }
    //UOJ228
    区间加减,区间开根,询问区间和
    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m;
    long long a[1000005];
    struct segtree
    {
        int l,r,max1,max2,num;
        long long sum;
    }tree[4000005];
    
    inline void pushup(int pos)
    {
        tree[pos].max1 = max(tree[pos<<1].max1,tree[pos<<1|1].max1);
        tree[pos].sum = tree[pos<<1].sum+tree[pos<<1|1].sum;
        tree[pos].num = 0;
        tree[pos].max2 = max(tree[pos<<1].max2,tree[pos<<1|1].max2);
        if(tree[pos].max1 == tree[pos<<1].max1) tree[pos].num += tree[pos<<1].num;
        else    tree[pos].max2 = max(tree[pos].max2,tree[pos<<1].max1);
        if(tree[pos].max1 == tree[pos<<1|1].max1)  tree[pos].num += tree[pos<<1|1].num;
        else    tree[pos].max2 = max(tree[pos].max2,tree[pos<<1|1].max1);
    }
    
    inline void pushdown(int pos)
    {
        if(tree[pos].max1 < tree[pos<<1].max1)
        {
            tree[pos<<1].sum -= (long long)tree[pos<<1].num*(tree[pos<<1].max1-tree[pos].max1);
            tree[pos<<1].max1 = tree[pos].max1;
        }
        if(tree[pos].max1 < tree[pos<<1|1].max1)
        {
            tree[pos<<1|1].sum -= (long long)tree[pos<<1|1].num*(tree[pos<<1|1].max1-tree[pos].max1);
            tree[pos<<1|1].max1 = tree[pos].max1;
        }
    }
    
    void build(int pos,int l,int r)
    {
        tree[pos].l = l;
        tree[pos].r = r;
        if(l == r)
        {
            scanf("%d",&tree[pos].max1);
            tree[pos].sum = tree[pos].max1;
            tree[pos].max2 = -1;
            tree[pos].num = 1;
            return;
        }
        int mid = (l+r)/2;
        build(pos<<1,l,mid);
        build(pos<<1|1,mid+1,r);
        pushup(pos);
    }
    
    void update(int pos,int l,int r,int x)
    {
        if(r < tree[pos].l || tree[pos].r < l || x >= tree[pos].max1)   return;
        if(l <= tree[pos].l && tree[pos].r <= r && tree[pos].max2 < x)
        {
            tree[pos].sum -= (long long)tree[pos].num*(tree[pos].max1-x);
            tree[pos].max1 = x;
            return;
        }
        pushdown(pos);
        update(pos<<1,l,r,x);
        update(pos<<1|1,l,r,x);
        pushup(pos);
    }
    
    long long getsum(int pos,int l,int r)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return 0;
        if(l <= tree[pos].l && tree[pos].r <= r)    return tree[pos].sum;
        pushdown(pos);
        return  getsum(pos<<1,l,r)+getsum(pos<<1|1,l,r);
    }
    
    int getmax(int pos,int l,int r)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return 0;
        if(l <= tree[pos].l && tree[pos].r <= r)    return tree[pos].max1;
        pushdown(pos);
        return max(getmax(pos<<1,l,r),getmax(pos<<1|1,l,r));
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            build(1,1,n);
            for(int i = 1;i <= m;i++)
            {
                int z,l,r,x;
                scanf("%d%d%d",&z,&l,&r);
                if(z == 0)
                {
                    scanf("%d",&x);
                    update(1,l,r,x);
                }
                else if(z == 1) printf("%d
    ",getmax(1,l,r));
                else    printf("%lld
    ",getsum(1,l,r));
            }
        }
        return 0;
    }
    //HDU5306
    区间最小值,询问区间最大值,询问区间和
    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define ls pos<<1
    #define rs pos<<1|1
    using namespace std;
    
    int n,m;
    char s[10];
    long long a[1000005];
    struct segtree
    {
        int l,r,nmax,pmax,nlazy,plazy,ncov,pcov;
    }tree[4000005];
    
    inline void pushup(int pos)
    {
        tree[pos].nmax = max(tree[ls].nmax,tree[rs].nmax);
        tree[pos].pmax = max(tree[ls].pmax,tree[rs].pmax);
    }
    
    inline void pushdown(int pos)
    {
        tree[ls].pmax = max(tree[ls].pmax,max(tree[pos].pcov,tree[pos].plazy+tree[ls].nmax));
        tree[rs].pmax = max(tree[rs].pmax,max(tree[pos].pcov,tree[pos].plazy+tree[rs].nmax));
        if(tree[pos].ncov == -INF)
        {
            tree[ls].nmax += tree[pos].nlazy;
            tree[rs].nmax += tree[pos].nlazy;
            if(tree[ls].ncov == -INF)
            {
                tree[ls].plazy = max(tree[ls].plazy,tree[ls].nlazy+tree[pos].plazy);
                tree[ls].nlazy += tree[pos].nlazy;
            }
            else
            {
                tree[ls].pcov = max(tree[ls].pcov,tree[ls].ncov+tree[pos].plazy);
                tree[ls].ncov = tree[ls].nmax;
            }
            if(tree[rs].ncov == -INF)
            {
                tree[rs].plazy = max(tree[rs].plazy,tree[rs].nlazy+tree[pos].plazy);
                tree[rs].nlazy += tree[pos].nlazy;
            }
            else
            {
                tree[rs].pcov = max(tree[rs].pcov,tree[rs].ncov+tree[pos].plazy);
                tree[rs].ncov = tree[rs].nmax;
            }
        }
        else
        {
            if(tree[ls].ncov == -INF)   tree[ls].plazy = max(tree[ls].plazy,tree[ls].nlazy+tree[pos].plazy);
            else    tree[ls].pcov = max(tree[ls].pcov,tree[ls].nmax+tree[pos].plazy);
            if(tree[rs].ncov == -INF)   tree[rs].plazy = max(tree[rs].plazy,tree[rs].nlazy+tree[pos].plazy);
            else    tree[rs].pcov = max(tree[rs].pcov,tree[rs].nmax+tree[pos].plazy);
            tree[ls].nmax = tree[pos].ncov;
            tree[rs].nmax = tree[pos].ncov;
            tree[ls].ncov = tree[pos].ncov;
            tree[rs].ncov = tree[pos].ncov;
            tree[ls].pcov = max(tree[ls].pcov,tree[pos].pcov);
            tree[rs].pcov = max(tree[rs].pcov,tree[pos].pcov);
        }
        tree[pos].nlazy = 0;
        tree[pos].plazy = 0;
        tree[pos].ncov = -INF;
        tree[pos].pcov = -INF;
    }
    
    void build(int pos,int l,int r)
    {
        tree[pos].l = l;
        tree[pos].r = r;
        tree[pos].ncov = -INF;
        tree[pos].pcov = -INF;
        tree[pos].nlazy = 0;
        tree[pos].plazy = 0;
        if(l == r)
        {
            scanf("%d",&tree[pos].nmax);
            tree[pos].pmax = tree[pos].nmax;
            return;
        }
        int mid = (l+r)/2;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(pos);
    }
    
    long long getans(int pos,int l,int r,int t)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return -INF;
        if(l <= tree[pos].l && tree[pos].r <= r)    return t?tree[pos].pmax:tree[pos].nmax;
        pushdown(pos);
        return  max(getans(ls,l,r,t),getans(rs,l,r,t));
    }
    
    
    void update1(int pos,int l,int r,int x)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return;
        if(l <= tree[pos].l && tree[pos].r <= r)
        {
            tree[pos].nmax += x;
            tree[pos].pmax = max(tree[pos].pmax,tree[pos].nmax);
            if(tree[pos].ncov == -INF)
            {
                tree[pos].nlazy += x;
                tree[pos].plazy = max(tree[pos].plazy,tree[pos].nlazy);
            }
            else
            {
                tree[pos].ncov = tree[pos].nmax;
                tree[pos].pcov = max(tree[pos].pcov,tree[pos].ncov);
            }
            return;
        }
        pushdown(pos);
        update1(ls,l,r,x);
        update1(rs,l,r,x);
        pushup(pos);
    }
    
    void update2(int pos,int l,int r,int x)
    {
        if(r < tree[pos].l || tree[pos].r < l)  return;
        if(l <= tree[pos].l && tree[pos].r <= r)
        {
            tree[pos].nmax = x;
            tree[pos].pmax = max(tree[pos].pmax,tree[pos].nmax);
            tree[pos].ncov = x;
            tree[pos].pcov = max(tree[pos].pcov,tree[pos].ncov);
            return;
        }
        pushdown(pos);
        update2(ls,l,r,x);
        update2(rs,l,r,x);
        pushup(pos);
    }
    
    int main()
    {
        scanf("%d",&n);
        build(1,1,n);
        scanf("%d",&m);
        for(int i = 1;i <= m;i++)
        {
            int l,r,x;
            scanf("%s%d%d",s,&l,&r);
            if(s[0] == 'Q') printf("%d
    ",getans(1,l,r,0));
            else if(s[0] == 'A')    printf("%d
    ",getans(1,l,r,1));
            else if(s[0] == 'P')
            {
                scanf("%d",&x);
                update1(1,l,r,x);
            }
            else
            {
                scanf("%d",&x);
                update2(1,l,r,x);
            }
        }
        return 0;
    }
    //TYVJ1518
    区间加减,区间覆盖,询问区间最大值,询问历史区间最大值

    #include<bits/stdc++.h>
    using namespace std;
    
    int n,m,a[200005],cnt[200005],next[200005],belong[200005],l[1005],r[1005];
    
    void build()
    {
        int len = sqrt(n);
        int num = (n+len-1)/len;
        if(n%len) num++;
        for(int i = 1;i <= num;i++)
        {
            l[i] = (i-1)*len+1;
            r[i] = i*len;
        }
        r[num] = n;
        for(int i = 1;i <= n;i++)   belong[i] = (i-1)/len+1;
        for(int i = n;i >= 1;i--)
        {
            int t = i+a[i];
            if(t > n)
            {
                cnt[i] = 1;
                next[i] = -1;
            }
            else if(belong[i] == belong[t])
            {
                cnt[i] = cnt[t]+1;
                next[i] = next[t];
            }
            else
            {
                cnt[i] = 1;
                next[i] = t;
            }
        }
    }
    
    void update(int pos,int x)
    {
        a[pos] = x;
        for(int i = pos;i >= l[belong[pos]];i--)
        {
            int t = i+a[i];
            if(t > n)
            {
                cnt[i] = 1;
                next[i] = -1;
            }
            else if(belong[i] == belong[t])
            {
                cnt[i] = cnt[t]+1;
                next[i] = next[t];
            }
            else
            {
                cnt[i] = 1;
                next[i] = t;
            }
        }
    }
    
    int getsum(int x)
    {
        int ans = cnt[x];
        while(next[x] > 0)
        {
            x = next[x];
            ans += cnt[x];
        }
        return ans;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        scanf("%d",&n);
        for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
        build();
        scanf("%d",&m);
        while(m--)
        {
            int x,y,z;
            scanf("%d",&x);
            if(x == 1)
            {
                scanf("%d",&y);
                printf("%d
    ",getsum(y+1));
            }
            else
            {
                scanf("%d%d",&y,&z);
                update(y+1,z);
            }
        }
        return 0;
    }
    块状数组
    int a[30005],num[30005],n,m;
    long long ans[30005];
    struct node
    {
        int l,r,num,belong;
        friend bool operator<(node a,node b)
        {
            if(a.belong == b.belong)    return a.r < b.r;
            return a.l < b.l;
        }
    }query[30005];
    
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            int size = sqrt(n);
            for(int i = 1;i <= n;i++)    scanf("%d",&a[i]);
            for(int i = 1;i <= m;i++)
            {
                scanf("%d%d",&query[i].l,&query[i].r);
                query[i].num = i;
                query[i].belong = (query[i].l-1)/size+1;
            }
            sort(query+1,query+1+m);
            memset(num,0,sizeof(num));
            int ll = 1,rr = 1;
            LL now = 1;
            num[a[1]]++;
            for(int i = 1;i <= m;i++)
            {
                while(rr < query[i].r)
                {
                    rr++;
                    num[a[rr]]++;
                    //now = ;
                }
                while(ll > query[i].l)
                {
                    ll--;
                    num[a[ll]]++;
                    //now = ;
                }
                while(ll < query[i].l)
                {
                    //now = ;
                    num[a[ll]]--;
                    ll++;
                }
                while(rr > query[i].r)
                {
                    //now = ;
                    num[a[rr]]--;
                    rr--;
                }
                ans[query[i].num] = now;
            }
            for(int i = 1;i <= m;i++)    printf("%lld
    ",ans[i]);
        }
        return 0;
    }
    莫队

    //1:INSERT post tot c1,c2,...ctot :在当前数列的第pos个数字后插入tot个数字
    //2:DELETE pos tot : 从当前数列的第pos个数字开始连续 删除tot个数字
    //3:MAKE-SAME pos tot c :将当前数列的第pos个数字开始连续的tot个数字统一修改为c
    //4:REVERSE pos tot : 翻转当前数列的第pos个数字来说的连续的tot个数字
    //5:GET-SUM pos tot :计算当前数列的第pos个数字来说的连续的tot个数字的和并输出
    //6:MAX-SUM :求出当前数列中和最大的一段序列,输出最大和
    #include<bits/stdc++.h>
    #define Key_value ch[ch[root][1]][0]
    #define N 500005
    #define INF 0x3f3f3f3f
    using namespace std;
    
    int n,m,a[N];
    char s[20];
    int pre[N],ch[N][2],key[N],size[N];
    int root,tot1,tot2,st[N];
    int sum[N],rev[N],same[N];
    int lx[N],rx[N],mx[N];
    
    //debug部分**********************************
    void Treavel(int x)
    {
        if(!x)  return;
        Treavel(ch[x][0]);
        printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d
    ",x,ch[x][0],ch[x][1],pre[x],size[x]);
        Treavel(ch[x][1]);
    }
    void debug()
    {
        printf("root:%d
    ",root);
        Treavel(root);
    }
    //以上是debug部分**************************************
    
    
    void NewNode(int &r,int father,int k)
    {
        if(tot2) r = st[tot2--];//取的时候是tot2--,存的时候就是++tot2
        else r = ++tot1;
        pre[r] = father;
        ch[r][0] = ch[r][1] = 0;
        key[r] = k;
        sum[r] = k;
        rev[r] = same[r] = 0;
        lx[r] = rx[r] = mx[r] = k;
        size[r] = 1;
    }
    
    void Update_Rev(int r)
    {
        if(!r)return;
        swap(ch[r][0],ch[r][1]);
        swap(lx[r],rx[r]);
        rev[r] ^= 1;
    }
    
    void Update_Same(int r,int v)
    {
        if(!r)return;
        key[r] = v;
        sum[r] = v*size[r];
        lx[r] = rx[r] = mx[r] = max(v,v*size[r]);
        same[r] = 1;
    }
    
    void push_up(int r)
    {
        int lson = ch[r][0], rson = ch[r][1];
        size[r] = size[lson]+size[rson]+1;
        sum[r] = sum[lson]+sum[rson]+key[r];
        lx[r] = max(lx[lson],sum[lson]+key[r]+max(0,lx[rson]));
        rx[r] = max(rx[rson],sum[rson]+key[r]+max(0,rx[lson]));
        mx[r] = max(0,rx[lson])+key[r]+max(0,lx[rson]);
        mx[r] = max(mx[r],max(mx[lson],mx[rson]));
    }
    
    void push_down(int r)
    {
        if(same[r])
        {
            Update_Same(ch[r][0],key[r]);
            Update_Same(ch[r][1],key[r]);
            same[r] = 0;
        }
        if(rev[r])
        {
            Update_Rev(ch[r][0]);
            Update_Rev(ch[r][1]);
            rev[r] = 0;
        }
    }
    
    void Build(int &x,int l,int r,int father)
    {
        if(l > r)   return;
        int mid = (l+r)/2;
        NewNode(x,father,a[mid]);
        Build(ch[x][0],l,mid-1,x);
        Build(ch[x][1],mid+1,r,x);
        push_up(x);
    }
    
    void Init()
    {
        root = tot1 = tot2 = 0;
        ch[root][0] = ch[root][1] = size[root] = pre[root] = 0;
        same[root] = rev[root] = sum[root] = key[root] = 0;
        lx[root] = rx[root] = mx[root] = -INF;
        NewNode(root,0,-1);
        NewNode(ch[root][1],root,-1);
        for(int i = 0;i < n;i++)    scanf("%d",&a[i]);
        Build(Key_value,0,n-1,ch[root][1]);
        push_up(ch[root][1]);
        push_up(root);
    }
    
    //旋转,0为左旋,1为右旋
    void Rotate(int x,int kind)
    {
        int y = pre[x];
        push_down(y);
        push_down(x);
        ch[y][!kind] = ch[x][kind];
        pre[ch[x][kind]] = y;
        if(pre[y])  ch[pre[y]][ch[pre[y]][1]==y] = x;
        pre[x] = pre[y];
        ch[x][kind] = y;
        pre[y] = x;
        push_up(y);
    }
    
    //Splay调整,将r结点调整到goal下面
    void Splay(int r,int goal)
    {
        push_down(r);
        while(pre[r] != goal)
        {
            if(pre[pre[r]] == goal)
            {
                push_down(pre[r]);
                push_down(r);
                Rotate(r,ch[pre[r]][0] == r);
            }
            else
            {
                push_down(pre[pre[r]]);
                push_down(pre[r]);
                push_down(r);
                int y = pre[r];
                int kind = ch[pre[y]][0]==y;
                if(ch[y][kind] == r)
                {
                    Rotate(r,!kind);
                    Rotate(r,kind);
                }
                else
                {
                    Rotate(y,kind);
                    Rotate(r,kind);
                }
            }
        }
        push_up(r);
        if(goal == 0) root = r;
    }
    
    int Get_kth(int r,int k)
    {
        push_down(r);
        int t = size[ch[r][0]] + 1;
        if(t == k)  return r;
        if(t > k)   return Get_kth(ch[r][0],k);
        else    return Get_kth(ch[r][1],k-t);
    }
    
    //在第pos个数后面插入tot个数
    void Insert(int pos,int tot)
    {
        for(int i = 0;i < tot;i++)scanf("%d",&a[i]);
        Splay(Get_kth(root,pos+1),0);
        Splay(Get_kth(root,pos+2),root);
        Build(Key_value,0,tot-1,ch[root][1]);
        push_up(ch[root][1]);
        push_up(root);
    }
    
    //删除子树
    void erase(int r)
    {
        if(!r)return;
        st[++tot2] = r;
        erase(ch[r][0]);
        erase(ch[r][1]);
    }
    
    //从第pos个数开始连续删除tot个数
    void Delete(int pos,int tot)
    {
        Splay(Get_kth(root,pos),0);
        Splay(Get_kth(root,pos+tot+1),root);
        erase(Key_value);
        pre[Key_value] = 0;
        Key_value = 0;
        push_up(ch[root][1]);
        push_up(root);
    }
    
    //将从第pos个数开始的连续的tot个数修改为c
    void Make_Same(int pos,int tot,int c)
    {
        Splay(Get_kth(root,pos),0);
        Splay(Get_kth(root,pos+tot+1),root);
        Update_Same(Key_value,c);
        push_up(ch[root][1]);
        push_up(root);
    }
    
    //将第pos个数开始的连续tot个数进行反转
    void Reverse(int pos,int tot)
    {
        Splay(Get_kth(root,pos),0);
        Splay(Get_kth(root,pos+tot+1),root);
        Update_Rev(Key_value);
        push_up(ch[root][1]);
        push_up(root);
    }
    
    //得到第pos个数开始的tot个数的和
    int Get_Sum(int pos,int tot)
    {
        Splay(Get_kth(root,pos),0);
        Splay(Get_kth(root,pos+tot+1),root);
        return sum[Key_value];
    }
    
    //得到第pos个数开始的tot个数中最大的子段和
    int Get_MaxSum(int pos,int tot)
    {
        Splay(Get_kth(root,pos),0);
        Splay(Get_kth(root,pos+tot+1),root);
        return mx[Key_value];
    }
    
    void InOrder(int r)
    {
        if(!r)  return;
        push_down(r);
        InOrder(ch[r][0]);
        printf("%d ",key[r]);
        InOrder(ch[r][1]);
    }
    
    
    
    int main()
    {
        scanf("%d%d",&n,&m);
        Init();
        int x,y,z;
        while(m--)
        {
            scanf("%s",s);
            if(strcmp(s,"INSERT") == 0)
            {
                scanf("%d%d",&x,&y);
                Insert(x,y);
            }
            else if(strcmp(s,"DELETE") == 0)
            {
                scanf("%d%d",&x,&y);
                Delete(x,y);
            }
            else if(strcmp(s,"MAKE-SAME") == 0)
            {
                scanf("%d%d%d",&x,&y,&z);
                Make_Same(x,y,z);
            }
            else if(strcmp(s,"REVERSE") == 0)
            {
                scanf("%d%d",&x,&y);
                Reverse(x,y);
            }
            else if(strcmp(s,"GET-SUM") == 0)
            {
                scanf("%d%d",&x,&y);
                printf("%d
    ",Get_Sum(x,y));
            }
            else if(strcmp(s,"MAX-SUM") == 0)   printf("%d
    ",Get_MaxSum(1,size[root]-2));
        }
        return 0;
    }
    splay tree

    //动态维护一组森林,要求支持一下操作:
    //link(a,b) : 如果a,b不在同一颗子树中,则通过在a,b之间连边的方式,连接这两颗子树
    //cut(a,b)  : 如果a,b在同一颗子树中,且a!=b,则将a视为这颗子树的根以后,切断b与其父亲结点的连接
    //ADD(a,b,w): 如果a,b在同一颗子树中,则将a,b之间路径上所有点的点权增加w
    //query(a,b): 如果a,b在同一颗子树中,返回a,b之间路径上点权的最大值
    #include<bits/stdc++.h>
    #define N 300005
    using namespace std;
    
    int n,q,op;
    int ch[N][2],pre[N],key[N];
    int add[N],rev[N],Max[N];
    bool rt[N];
    vector<int> v[N];
    
    void Update_Add(int r,int d)
    {
        if(!r)return;
        key[r] += d;
        add[r] += d;
        Max[r] += d;
    }
    
    void Update_Rev(int r)
    {
        if(!r)return;
        swap(ch[r][0],ch[r][1]);
        rev[r] ^= 1;
    }
    
    void push_down(int r)
    {
        if(add[r])
        {
            Update_Add(ch[r][0],add[r]);
            Update_Add(ch[r][1],add[r]);
            add[r] = 0;
        }
        if(rev[r])
        {
            Update_Rev(ch[r][0]);
            Update_Rev(ch[r][1]);
            rev[r] = 0;
        }
    }
    
    void push_up(int r)
    {
        Max[r] = max(max(Max[ch[r][0]],Max[ch[r][1]]),key[r]);
    }
    
    void Rotate(int x)
    {
        int y = pre[x], kind = ch[y][1] == x;
        ch[y][kind] = ch[x][!kind];
        pre[ch[y][kind]] = y;
        pre[x] = pre[y];
        pre[y] = x;
        ch[x][!kind] = y;
        if(rt[y])
        {
            rt[y] = 0;
            rt[x] = 1;
        }
        else    ch[pre[x]][ch[pre[x]][1]==y] = x;
        push_up(y);
    }
    
    //P函数先将根结点到r的路径上所有的结点的标记逐级下放
    void P(int r)
    {
        if(!rt[r])  P(pre[r]);
        push_down(r);
    }
    
    void Splay(int r)
    {
        P(r);
        while(!rt[r])
        {
            int f = pre[r],ff = pre[f];
            if(rt[f])   Rotate(r);
            else if((ch[ff][1] == f) == (ch[f][1] == r))
            {
                Rotate(f);
                Rotate(r);
            }
            else
            {
                Rotate(r);
                Rotate(r);
            }
        }
        push_up(r);
    }
    
    int Access(int x)
    {
        int y = 0;
        for(;x;x = pre[y = x])
        {
            Splay(x);
            rt[ch[x][1]] = 1;
            rt[ch[x][1]=y] = 0;
            push_up(x);
        }
        return y;
    }
    
    //判断是否是同根(真实的树,非splay)
    bool judge(int u,int v)
    {
        while(pre[u])   u = pre[u];
        while(pre[v])   v = pre[v];
        return u == v;
    }
    
    //使r成为它所在的树的根
    void mroot(int r)
    {
        Access(r);
        Splay(r);
        Update_Rev(r);
    }
    
    //调用后u是原来u和v的lca,v和ch[u][1]分别存着lca的2个儿子
    //(原来u和v所在的2颗子树)
    void lca(int &u,int &v)
    {
        Access(v),v = 0;
        while(u)
        {
            Splay(u);
            if(!pre[u]) return;
            rt[ch[u][1]] = 1;
            rt[ch[u][1] = v] = 0;
            push_up(u);
            u = pre[v = u];
        }
    }
    
    void link(int u,int v)
    {
        if(judge(u,v))
        {
            puts("-1");
            return;
        }
        mroot(u);
        pre[u] = v;
    }
    
    //使u成为u所在树的根,并且v和它父亲的边断开
    void cut(int u,int v)
    {
        if(u == v || !judge(u,v))
        {
            puts("-1");
            return;
        }
        mroot(u);
        Splay(v);
        pre[ch[v][0]] = pre[v];
        pre[v] = 0;
        rt[ch[v][0]] = 1;
        ch[v][0] = 0;
        push_up(v);
    }
    
    void ADD(int u,int v,int w)
    {
        if(!judge(u,v))
        {
            puts("-1");
            return;
        }
        lca(u,v);
        Update_Add(ch[u][1],w);
        Update_Add(v,w);
        key[u] += w;
        push_up(u);
    }
    
    void query(int u,int v)
    {
        if(!judge(u,v))
        {
            puts("-1");
            return;
        }
        lca(u,v);
        printf("%d
    ",max(max(Max[v],Max[ch[u][1]]),key[u]));
    }
    
    void init()
    {
        for(int i = 1;i <= n;i++)   v[i].clear();
        for(int i = 0;i <= n;i++)
        {
            pre[i] = 0;
            ch[i][0] = ch[i][1] = 0;
            rev[i] = 0;
            add[i] = 0;
            rt[i] = 1;
        }
        Max[0] = -2000000000;
    }
    
    void dfs(int u)
    {
        for(int i = 0;i < v[u].size();i++)
        {
            int t = v[u][i];
            if(pre[t] != 0)continue;
            pre[t] = u;
            dfs(t);
        }
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            init();
            for(int i = 1;i < n;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                v[x].push_back(y);
                v[y].push_back(x);
            }
            for(int i = 1;i <= n;i++)
            {
                scanf("%d",&key[i]);
                Max[i] = key[i];
            }
            scanf("%d",&q);
            pre[1] = -1;
            dfs(1);
            pre[1] = 0;
            while(q--)
            {
                scanf("%d",&op);
                if(op == 1)
                {
                    int x,y;
                    scanf("%d%d",&x,&y);
                    link(x,y);
                }
                else if(op == 2)
                {
                    int x,y;
                    scanf("%d%d",&x,&y);
                    cut(x,y);
                }
                else if(op == 3)
                {
                    int w,x,y;
                    scanf("%d%d%d",&w,&x,&y);
                    ADD(x,y,w);
                }
                else
                {
                    int x,y;
                    scanf("%d%d",&x,&y);
                    query(x,y);
                }
            }
            printf("
    ");
        }
        return 0;
    }
    动态树LCT

    主席树:

    int n,q,m,tot,a[N],b[N];
    int tree[N],lson[N*30],rson[N*30],c[N*30];
    
    void init_hash()
    {
        for(int i = 1;i <= n;i++) b[i]=a[i];
        sort(b+1,b+n+1);
        m = unique(b+1,b+n+1)-b-1;
    }
    
    int gethash(int x)
    {
        return lower_bound(b+1,b+1+m,x)-b;
    }
    
    void build(int &now,int l,int r)
    {
        now = tot++;
        c[now] = 0;
        if(l == r)  return;
        int mid = (l+r)/2;
        build(lson[now],l,mid);
        build(rson[now],mid+1,r);
    }
    
    void update(int &now,int last,int l,int r,int pos,int x)
    {
        now = tot++;
        lson[now] = lson[last];
        rson[now] = rson[last];
        c[now] = c[last]+x;
        if(l == r)  return;
        int mid = (l+r)/2;
        if(pos <= mid)  update(lson[now],lson[last],l,mid,pos,x);
        else    update(rson[now],rson[last],mid+1,r,pos,x);
    }
    
    int query(int lt,int rt,int l,int r,int k)
    {
        if(l == r)  return l;
        int mid = (l+r)/2;
        if(c[lson[rt]]-c[lson[lt]] >= k)    return query(lson[lt],lson[rt],l,mid,k);
        return query(rson[lt],rson[rt],mid+1,r,k-c[lson[rt]]+c[lson[lt]]);
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        while(~scanf("%d%d",&n,&q))
        {
            for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
            init_hash();
            tot = 0;
            build(tree[0],1,m);
            for(int i = 1;i <= n;i++)    update(tree[i],tree[i-1],1,m,gethash(a[i]),1);
            while(q--)
            {
                int l,r,k;
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",b[query(tree[l-1],tree[r],1,m,k)]);
            }
        }
        return 0;
    }
    静态区间第k大
    int n,q,m,tot,a[N],b[N];
    int tree[N],lson[N*100],rson[N*100],c[N*100];
    map<int,int> mp;
    
    int build(int l,int r)
    {
        int now = tot++;
        c[now] = 0;
        if(l == r)  return now;
        int mid = (l+r)/2;
        lson[now] = build(l,mid);
        rson[now] = build(mid+1,r);
        return now;
    }
    
    int update(int last,int pos,int x)
    {
        int now = tot++,t = now;
        c[now] = c[last]+x;
        int l = 1,r = n;
        while(l < r)
        {
            int mid  = (l+r)/2;
            if(pos <= mid)
            {
                lson[now] = tot++;
                rson[now] = rson[last];
                now = lson[now];
                last = lson[last];
                r = mid;
            }
            else
            {
                rson[now] = tot++;
                lson[now] = lson[last];
                now = rson[now];
                last = rson[last];
                l = mid+1;
            }
            c[now] = c[last]+x;
        }
        return t;
    }
    
    int query(int pos,int now,int l,int r)
    {
        if(l == r)  return c[now];
        int mid = (l+r)/2;
        if(pos <= mid)  return query(pos,lson[now],l,mid)+c[rson[now]];
        return query(pos,rson[now],mid+1,r);
    }
    
    int main()
    {
    
        while(~scanf("%d",&n))
        {
            for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
            tot = 0;
            tree[0] = build(1,n);
            for(int i = 1;i <= n;i++)
            {
                if(mp.find(a[i]) == mp.end())   tree[i] = update(tree[i-1],i,1);
                else
                {
                    int t = update(tree[i-1],mp[a[i]],-1);
                    tree[i] = update(t,i,1);
                }
                mp[a[i]] = i;
            }
            scanf("%d",&q);
            while(q--)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d
    ",query(l,tree[r],1,n));
            }
        }
        return 0;
    }
    静态区间查询不同的数个数
    int n,q,m,tot,cnt,a[N],b[N],p[N],f[N*2],rmq[N*2];
    int tree[N],lson[N*40],rson[N*40],c[N*40];
    vector<int> v[N];
    struct ST
    {
        int mm[2*N],dp[2*N][20];
        void init(int n)
        {
            mm[0] = -1;
            for(int i = 1;i <= n;i++)
            {
                mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
                dp[i][0] = i;
            }
            for(int j = 1;j <= mm[n];j++)
            {
                for(int i = 1;i+(1<<j)-1 <= n;i++)  dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
            }
        }
        int query(int a,int b)
        {
            if(a > b)   swap(a,b);
            int k = mm[b-a+1];
            return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
        }
    }st;
    
    void inithash()
    {
        for(int i = 1;i <= n;i++)   b[i] = a[i];
        sort(b+1,b+1+n);
        m = unique(b+1,b+1+n)-b-1;
    }
    
    int gethash(int x)
    {
        return lower_bound(b+1,b+1+m,x)-b;
    }
    
    void dfs(int now,int pre,int dep)
    {
        f[++cnt] = now;
        rmq[cnt] = dep;
        p[now] = cnt;
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t == pre)    continue;
            dfs(t,now,dep+1);
            f[++cnt] = now;
            rmq[cnt] = dep;
        }
    }
    
    void initlca(int root,int n)
    {
        cnt = 0;
        dfs(root,root,0);
        st.init(2*n-1);
    }
    
    int querylca(int x,int y)
    {
        return f[st.query(p[x],p[y])];
    }
    
    int build(int l,int r)
    {
        int now = tot++;
        c[now] = 0;
        if(l == r)  return now;
        int mid = (l+r)/2;
        lson[now] = build(l,mid);
        rson[now] = build(mid+1,r);
        return now;
    }
    
    int update(int last,int pos,int x)
    {
        int now = tot++,t = now;
        c[now] = c[last]+x;
        int l = 1,r = m;
        while(l < r)
        {
            int mid  = (l+r)/2;
            if(pos <= mid)
            {
                lson[now] = tot++;
                rson[now] = rson[last];
                now = lson[now];
                last = lson[last];
                r = mid;
            }
            else
            {
                rson[now] = tot++;
                lson[now] = lson[last];
                now = rson[now];
                last = rson[last];
                l = mid+1;
            }
            c[now] = c[last]+x;
        }
        return t;
    }
    
    void dfsbuild(int now,int pre)
    {
        tree[now] = update(tree[pre],gethash(a[now]),1);
        for(int i = 0;i < v[now].size();i++)
        {
            int t = v[now][i];
            if(t == pre)    continue;
            dfsbuild(t,now);
        }
    }
    
    int query(int lt,int rt,int lcat,int pos,int k,int l,int r)
    {
        if(l == r)  return l;
        int mid = (l+r)/2;
        int t = c[lson[lt]]+c[lson[rt]]-2*c[lson[lcat]];
        if(pos >= l && pos <= mid)  t++;
        if(t >= k)  return query(lson[lt],lson[rt],lson[lcat],pos,k,l,mid);
        return query(rson[lt],rson[rt],rson[lcat],pos,k-t,mid+1,r);
    }
    
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i = 1;i <= n;i++)   scanf("%d",&a[i]);
        inithash();
        tot = 0;
        for(int i = 1;i < n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            v[x].push_back(y);
            v[y].push_back(x);
        }
        initlca(1,n);
        tree[0] = build(1,m);
        dfsbuild(1,0);
        while(q--)
        {
            int x,y,k;
            scanf("%d%d%d",&x,&y,&k);
            int t = querylca(x,y);
            printf("%d
    ",b[query(tree[x],tree[y],tree[t],gethash(a[t]),k,1,m)]);
        }
        return 0;
    }
    树上路径点权第k大
    int n,q,m,tot,a[N],b[N],use[N];;
    int tree[N],tree2[N],lson[N*50],rson[N*50],c[N*50];
    
    struct Query
    {
        int kind;
        int l,r,k;
    }query[10010];
    
    void Init_hash(int k)
    {
        sort(b,b+k);
        m = unique(b,b+k) - b;
    }
    int hash(int x)
    {
        return lower_bound(b,b+m,x)-b;
    }
    int build(int l,int r)
    {
        int root = tot++;
        c[root] = 0;
        if(l != r)
        {
            int mid = (l+r)/2;
            lson[root] = build(l,mid);
            rson[root] = build(mid+1,r);
        }
        return root;
    }
    
    int Insert(int root,int pos,int val)
    {
        int newroot = tot++, tmp = newroot;
        int l = 0, r = m-1;
        c[newroot] = c[root] + val;
        while(l < r)
        {
            int mid = (l+r)>>1;
            if(pos <= mid)
            {
                lson[newroot] = tot++; rson[newroot] = rson[root];
                newroot = lson[newroot]; root = lson[root];
                r = mid;
            }
            else
            {
                rson[newroot] = tot++; lson[newroot] = lson[root];
                newroot = rson[newroot]; root = rson[root];
                l = mid+1;
            }
            c[newroot] = c[root] + val;
        }
        return tmp;
    }
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void add(int x,int pos,int val)
    {
        while(x <= n)
        {
            tree2[x] = Insert(tree2[x],pos,val);
            x += lowbit(x);
        }
    }
    int sum(int x)
    {
        int ret = 0;
        while(x > 0)
        {
            ret += c[lson[use[x]]];
            x -= lowbit(x);
        }
        return ret;
    }
    int Query(int left,int right,int k)
    {
        int left_root = tree[left-1];
        int right_root = tree[right];
        int l = 0, r = m-1;
        for(int i = left-1;i;i -= lowbit(i)) use[i] = tree2[i];
        for(int i = right;i ;i -= lowbit(i)) use[i] = tree2[i];
        while(l < r)
        {
            int mid = (l+r)/2;
            int tmp = sum(right) - sum(left-1) + c[lson[right_root]] - c[lson[left_root]];
            if(tmp >= k)
            {
                r = mid;
                for(int i = left-1; i ;i -= lowbit(i))
                    use[i] = lson[use[i]];
                for(int i = right; i; i -= lowbit(i))
                    use[i] = lson[use[i]];
                left_root = lson[left_root];
                right_root = lson[right_root];
            }
            else
            {
                l = mid+1;
                k -= tmp;
                for(int i = left-1; i;i -= lowbit(i))
                    use[i] = rson[use[i]];
                for(int i = right;i ;i -= lowbit(i))
                    use[i] = rson[use[i]];
                left_root = rson[left_root];
                right_root = rson[right_root];
            }
        }
        return l;
    }
    void Modify(int x,int p,int d)
    {
        while(x <= n)
        {
            tree2[x] = Insert(tree2[x],p,d);
            x += lowbit(x);
        }
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&q);
            tot = 0;
            m = 0;
            for(int i = 1;i <= n;i++)
            {
                scanf("%d",&a[i]);
                b[m++] = a[i];
            }
            char op[10];
            for(int i = 0;i < q;i++)
            {
                scanf("%s",op);
                if(op[0] == 'Q')
                {
                    query[i].kind = 0;
                    scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k);
                }
                else
                {
                    query[i].kind = 1;
                    scanf("%d%d",&query[i].l,&query[i].r);
                    b[m++] = query[i].r;
                }
            }
            Init_hash(m);
            tree[0] = build(0,m-1);
            for(int i = 1;i <= n;i++)
                tree[i] = Insert(tree[i-1],hash(a[i]),1);
            for(int i = 1;i <= n;i++)
                tree2[i] = tree[0];
            for(int i = 0;i < q;i++)
            {
                if(query[i].kind == 0)
                    printf("%d
    ",b[Query(query[i].l,query[i].r,query[i].k)]);
                else
                {
                    Modify(query[i].l,hash(a[query[i].l]),-1);
                    Modify(query[i].l,hash(query[i].r),1);
                    a[query[i].l] = query[i].r;
                }
            }
        }
        return 0;
    }
    树状数组+主席树 动态第k大

  • 相关阅读:
    第三次个人作业
    第二次结对作业
    第一次结对作业
    第二次编程作业
    第一次编程
    第一次博客作业
    个人总结
    第二次结对作业
    软件工程-个人总结
    第三次个人作业
  • 原文地址:https://www.cnblogs.com/zhurb/p/7355522.html
Copyright © 2011-2022 走看看