zoukankan      html  css  js  c++  java
  • COJ968 WZJ的数据结构(负三十二)

    WZJ的数据结构(负三十二)
    难度级别:D; 运行时间限制:5000ms; 运行空间限制:262144KB; 代码长度限制:2000000B
    试题描述

    给你一棵N个点的无根树,边上均有权值,每个点上有一盏灯,初始均亮着。请你设计一个数据结构,回答M次操作。

    1 x:将节点x上的灯拉一次,即亮变灭,灭变亮。

    2 x k:询问当前所有亮灯的节点中距离x第k小的距离(注意如果x亮着也算入)。

    输入
    第一行为一个正整数N。
    第二行到第N行每行三个正整数ui,vi,wi。表示一条树边从ui到vi,距离为wi。
    第N+1行为一个正整数M。
    最后M行每行三个或两个正整数,格式见题面。
    输出
    对于每个询问操作,输出答案。
    输入示例
    10
    1 2 2
    1 3 1
    1 4 3
    1 5 2
    4 6 2
    4 7 1
    6 8 1
    7 9 2
    7 10 1
    5
    2 1 4
    1 5
    2 1 4
    2 1 9
    2 1 1
    输出示例
    2
    3
    6
    0
    其他说明
    1<=N,M<=50000
    1<=x,ui,vi<=N,1<=v,wi<=1000

    动态树分治的码农题啦。

    对于每个节点用两棵Treap分别维护子树中亮灯的节点到其距离与子树中亮灯的节点到其父亲距离。

    修改直接insert/remove。

    询问先二分答案,转化成判定问题,这很容易在Treap上做。

    修改O(log^2n),询问O(log^3n),常数还挺小的。

    说起来还真是简单呢!写了2h+。

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    struct Node {
        Node* ch[2];
        int r,s,v;
        void maintain() {s=ch[0]->s+ch[1]->s+1;}
    }nodes[maxn*20],*null=&nodes[0];
    int ToT;queue<Node*> Q;
    Node* newnode(int v) {
        Node* o;
        if(Q.empty()) o=&nodes[++ToT];
        else o=Q.front(),Q.pop();
        o->v=v;o->s=1;o->ch[0]=o->ch[1]=null;o->r=rand();
        return o;
    }
    void del(Node* &o) {Q.push(o);o=null;}
    void rotate(Node* &o,int d) {
        Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
        o->maintain();k->maintain();o=k;
    }
    void insert(Node* &o,int v) {
        if(o==null) o=newnode(v);
        else {
            int d=v>o->v;insert(o->ch[d],v);
            if(o->ch[d]->r>o->r) rotate(o,d^1);
            else o->maintain();
        }
    }
    void remove(Node* &o,int v) {
        if(o->v==v) {
            Node* k=o;
            if(o->ch[0]==null) o=o->ch[1],del(k);
            else if(o->ch[1]==null) o=o->ch[0],del(k);
            else {
                int d=o->ch[0]->r>o->ch[1]->r;
                rotate(o,d);remove(o->ch[d],v);
            }
        }
        else remove(o->ch[v>o->v],v);
        if(o!=null) o->maintain();
    }
    int query(Node* &o,int v) {
        if(o==null) return 0;
        if(v>o->v) return query(o->ch[1],v)+o->ch[0]->s+1;
        return query(o->ch[0],v);
    }
    int n,m,first[maxn],next[maxn<<1],to[maxn<<1],dis[maxn<<1],e;
    void AddEdge(int w,int v,int u) {
        dis[++e]=w;to[e]=v;next[e]=first[u];first[u]=e;
        dis[++e]=w;to[e]=u;next[e]=first[v];first[v]=e;
    }
    int dep[maxn],mn[maxn<<1][20],Log[maxn<<1],cnt,pos[maxn];
    void dfs(int x,int fa) {
        mn[++cnt][0]=dep[x];pos[x]=cnt;
        ren if(to[i]!=fa) {
            dep[to[i]]=dep[x]+dis[i];
            dfs(to[i],x);
            mn[++cnt][0]=dep[x];
        }
    }
    void pre() {
        Log[0]=-1;
        rep(i,1,cnt) Log[i]=Log[i>>1]+1;
        for(int j=1;(1<<j)<=cnt;j++)
           for(int i=1;i+(1<<j)-1<=cnt;i++)
              mn[i][j]=min(mn[i][j-1],mn[i+(1<<j-1)][j-1]);
    }
    int dist(int x,int y) {
        int ans=dep[x]+dep[y];
        x=pos[x];y=pos[y];if(x>y) swap(x,y);
        int k=Log[y-x+1];
        return ans-2*min(mn[x][k],mn[y-(1<<k)+1][k]);
    }
    int f[maxn],s[maxn],vis[maxn],size,rt;
    void getroot(int x,int fa) {
        s[x]=1;int maxs=0;
        ren if(to[i]!=fa&&!vis[to[i]]) {
            getroot(to[i],x);
            s[x]+=s[to[i]];
            maxs=max(maxs,s[to[i]]);
        }
        f[x]=max(size-s[x],maxs);
        if(f[x]<f[rt]) rt=x;
    }
    int fa[maxn];
    void solve(int x,int F) {
        vis[x]=1;fa[x]=F;
        ren if(!vis[to[i]]) {
            f[0]=size=s[to[i]];getroot(to[i],rt=0);
            solve(rt,x);
        }
    }
    Node *root[maxn],*root2[maxn];
    void turn_on(int x) {
        insert(root[x],0);
        for(int i=x;fa[i];i=fa[i]) {
            int D=dist(x,fa[i]);
            insert(root[fa[i]],D);
            insert(root2[i],D);
        }
    }
    void turn_off(int x) {
        remove(root[x],0);
        for(int i=x;fa[i];i=fa[i]) {
            int D=dist(x,fa[i]);
            remove(root[fa[i]],D);
            remove(root2[i],D);
        }
    }
    int query(int x,int v) {
        int ans=query(root[x],++v);
        for(int i=x;fa[i];i=fa[i]) {
            int D=dist(x,fa[i]);
            ans+=query(root[fa[i]],v-D)-query(root2[i],v-D);
        }
        return ans;
    }
    int mark[maxn];
    int main() {
        n=read();
        rep(i,1,n) root[i]=root2[i]=null;
        rep(i,2,n) AddEdge(read(),read(),read());
        dfs(1,0);pre();
        f[0]=size=n;getroot(1,rt=0);
        solve(rt,0);
        rep(i,1,n) turn_on(i);
        m=read();
        while(m--) {
            if(read()==1) {
                int x=read();
                if(mark[x]) turn_on(x);
                else turn_off(x);
                mark[x]^=1;
            }
            else {
                int x=read(),k=read();
                int l=0,r=1<<30,mid;
                while(l<r) if(query(x,mid=l+r>>1)>=k) r=mid; else l=mid+1; 
                printf("%d
    ",l);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    OPENCV图像变换-1
    OPENCV形态学操作1
    OPENCV基本滤波算法
    OSX下编译安装opencv3.1.0与opencv_contrib_master
    iOS8学习笔记-构建多视图应用程序
    iOS8学习笔记2--autolayout
    iOS学习笔记1--在xcode6以上的版本中不使用storyboard以及部分控件使用
    Objective-c学习笔记3
    objective-c学习笔记2
    objective-c学习笔记
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4699480.html
Copyright © 2011-2022 走看看