[HNOI2015] pick fruit - DFS sequence, the scanning lines, tree line segment tree sleeve

Given a tree, the tree has \ (P \) paths, respectively, the right value \ (C_i \) . Given \ (q \) th inquiry, asking each given a path, ask all the sub-path is a tree path of inquiry path, the weight of the \ (k \) small is. \ (n \ leq 40000 \)

Solution

Consider a given path \ ((a, b) \ ) is the interrogation path \ ((u, v) \ ) condition of the sub-path, may wish to set \ (a, u \) are each smaller sequence that DFS

  • If \ ((a, b) \ ) is a straight-chain, then the \ (dfn [u] \ notin [dfn [x], fin [x]], dfn [v] \ in [dfn [b], fin [b ]] \) , where \ (X \) is the \ (a \) to \ (B \) take the first point encountered, this can be determined using a multiplier
  • If \ ((a, b) \ ) is bent chain, then \ (dfn [u] \ in [dfn [a], fin [a]], dfn [v] \ in [dfn [b], fin [b ]] \)

So the question into a number of rectangular two-dimensional plane, given \ (q \) a point to ask, ask each rectangle covering all points in this section \ (k \) rectangular weight is much smaller weights

If this is not the first \ (k \) requirements, direct scanning line, segment tree maintenance can be

Now more \ (K \) requirement, then segment tree to tree cover segment, to maintain the outer subscript inner maintain weight

#include <bits/stdc++.h>
using namespace std;

const int N = 200005;
const int M = 2e7;
const int lim = 1e9;

int n,p,q,a[N],b[N],c[N],u[N],v[N],k[N],fa[N][19],dep[N],t1,t2,t3;
int dfn[N],fin[N],ind,nrect,ans[N];
vector <int> g[N];

struct point {
    int x,y,k;
} pt[N];

struct rect {
    int x1,y1,x2,y2,v;
} rec[N];

struct query {
    int x,t,k,id;
};

struct event {
    int l,r,t,v;
};

vector <query> que[N];
vector <event> evp[N],evn[N];

void dfs(int p) {
    dfn[p]=++ind;
    for(int i=1;i<19;i++) fa[p][i]=fa[fa[p][i-1]][i-1];
    for(int q:g[p]) if(dfn[q]==0) dep[q]=dep[p]+1, fa[q][0]=p, dfs(q);
    fin[p]=ind;
}

int getpoint(int p,int q) {
    if(dep[p]<dep[q]) swap(p,q);
    for(int i=18;i>=0;--i) if(dep[fa[p][i]]>dep[q]) p=fa[p][i];
    return p;
}

namespace iseg {
    int ch[M][2],a[M],ind;
    void modify(int p,int l,int r,int pos,int val) {
        a[p]+=val;
        if(l<r) {
            if(pos<=(l+r)/2) {
                if(ch[p][0]==0) ch[p][0]=++ind;
                modify(ch[p][0],l,(l+r)/2,pos,val);
            }
            else {
                if(ch[p][1]==0) ch[p][1]=++ind;
                modify(ch[p][1],(l+r)/2+1,r,pos,val);
            }
        }
    }
    int newnode() {
        return ++ind;
    }
    int query(int p,int l,int r,int ql,int qr) {
        if(l>qr || r<ql || p==0) return 0;
        if(l>=ql&&r<=qr) return a[p];
        return query(ch[p][0],l,(l+r)/2,ql,qr)+query(ch[p][1],(l+r)/2+1,r,ql,qr);
    }
}

namespace oseg {
    int a[M];
    void modify(int p,int l,int r,int ql,int qr,int pos,int val) {
        if(l>qr || r<ql) return;
        if(l>=ql&&r<=qr) {
            if(a[p]==0) a[p]=iseg::newnode();
            iseg::modify(a[p],1,lim,pos,val);
        }
        else {
            modify(p*2,l,(l+r)/2,ql,qr,pos,val);
            modify(p*2+1,(l+r)/2+1,r,ql,qr,pos,val);
        }
    }
    int query(int p,int l,int r,int x,int vl,int vr) {
        int tmp = iseg::query(a[p],1,lim,vl,vr);
        if(l==r) {
            return tmp;
        }
        else {
            if(x<=(l+r)/2) return tmp + query(p*2,l,(l+r)/2,x,vl,vr);
            else return tmp + query(p*2+1,(l+r)/2+1,r,x,vl,vr);
        }
    }
}

namespace seq {
    vector <int> a[N];
    void modify(int ql,int qr,int pos) {
        oseg::modify(1,1,n,ql,qr,pos,1);
    }
    void erase(int ql,int qr,int pos) {
        oseg::modify(1,1,n,ql,qr,pos,-1);
    }
    int query(int x,int vl,int vr) {
        return oseg::query(1,1,n,x,vl,vr);
    }
    int kth(int x,int k) {
        int l=0,r=1e9;
        while(l<r) {
            int mid=(l+r)/2;
            if(query(x,1,mid)>=k) r=mid;
            else l=mid+1;
        }
        return l;
    }
}

void read() {
    ios::sync_with_stdio(false);
    cin>>n>>p>>q;
    for(int i=1;i<n;i++) {
        cin>>t1>>t2;
        g[t1].push_back(t2);
        g[t2].push_back(t1);
    }
    for(int i=1;i<=p;i++) {
        cin>>a[i]>>b[i]>>c[i];
    }
    for(int i=1;i<=q;i++) {
        cin>>u[i]>>v[i]>>k[i];
    }
    dfs(1);
}

void make() {
    for(int i=1;i<=p;i++) {
        if(dfn[a[i]]>dfn[b[i]]) swap(a[i],b[i]);
        if(dfn[a[i]]<=dfn[b[i]] && fin[a[i]]>=dfn[b[i]]) {
            a[i]=getpoint(a[i],b[i]);
            rec[++nrect]={1,dfn[b[i]],dfn[a[i]]-1,fin[b[i]],c[i]};
            rec[++nrect]={fin[a[i]]+1,dfn[b[i]],n,fin[b[i]],c[i]};
        }
        else {
            rec[++nrect]={dfn[a[i]],dfn[b[i]],fin[a[i]],fin[b[i]],c[i]};
        }
    }
    for(int i=1;i<=q;i++) {
        if(dfn[u[i]]>dfn[v[i]]) swap(u[i],v[i]);
        pt[i]={dfn[u[i]],dfn[v[i]],k[i]};
    }
    for(int i=1;i<=nrect;i++) {
        if(rec[i].x1>rec[i].x2 || rec[i].y1>rec[i].y2) continue;
        evp[rec[i].y1].push_back({rec[i].x1,rec[i].x2,rec[i].y1,rec[i].v});
        evn[rec[i].y2].push_back({rec[i].x1,rec[i].x2,rec[i].y2,rec[i].v});
        evp[rec[i].x1].push_back({rec[i].y1,rec[i].y2,rec[i].x1,rec[i].v});
        evn[rec[i].x2].push_back({rec[i].y1,rec[i].y2,rec[i].x2,rec[i].v});
    }
    for(int i=1;i<=q;i++) {
        que[pt[i].y].push_back({pt[i].x,pt[i].y,pt[i].k,i});
    }
}

void solve() {
    for(int i=1;i<=n;i++) {
        for(event e:evp[i]) {
            seq::modify(e.l,e.r,e.v);
        }
        for(query q:que[i]) {
            ans[q.id]=seq::kth(q.x,q.k);
        }
        for(event e:evn[i]) {
            seq::erase(e.l,e.r,e.v);
        }
    }
}

void print() {
    for(int i=1;i<=q;i++) cout<<ans[i]<<endl;
}

signed main() {
    read();
    make();
    solve();
    print();
}

Guess you like

Origin www.cnblogs.com/mollnn/p/12516901.html