hdu 4366 分块 or 线段树。

题意:http://acm.hdu.edu.cn/showproblem.php?pid=4366

         给你一棵树,每个结点有两个属性值,1:能力值  2:忠诚度

         然后m个询问,每次询问一个整数u,求u的子树中能力值大于u的且忠诚度最大的点的编号

写线段树wa了。。不改了。。
这里的从能力大的到小的排序的做法还是很普遍的。。
参考http://blog.csdn.net/julyana_lin/article/details/7866449

    #include<bits/stdc++.h>
using namespace std;
#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define MP make_pair
#define ULL unsigned long long
#define LL   long long
#define inf 0x3f3f3f3f
#define md ((ll+rr)>>1)
#define ls (i<<1)
#define rs (ls|1)
#define eps 1e-8
#define ree freopen("in.txt","r",stdin);
#define bug pf("----------------");
#define N 50010
#define mod 475
#define double long double
#define  pii pair<int,int>
#define MP make_pair
//2017年09月07日09:54:16

int n,m;
struct Node{
    int id,x,y;
    bool friend operator<(Node a,Node b){
        if(a.x!=b.x) return a.x>b.x;
        else return a.y>b.y;
    }
}a[N];
int e;
int st[N],ed[N];
int ans[N];
int col;
int fst[N<<1],vv[N<<1],nxt[N<<1];
void dfs(int u){
    st[u]=++col;
    for(int i=fst[u];~i;i=nxt[i]){
        int v=vv[i];
        dfs(v);
    }
    ed[u]=col;
}
int mx[N<<2];
int query(int l,int r,int ll,int rr,int i){
    if(l>r)return -1;
    if(l<=ll&&rr<=r){
        return mx[i];
    }
    if(md>=r)return query(l,r,ll,md,ls);
    else if(md<l)return query(l,r,md+1,rr,rs);
    else return max(query(l,md,ll,md,ls),query(md+1,r,md+1,rr,rs));
}
void update(int p,int val,int ll,int rr,int i){
    if(ll==rr&&ll==p){
        mx[ll]=val;return ;
    }
    if(md>=p)update(p,val,ll,md,ls);
    else if(md<p)update(p,val,md+1,rr,rs);
    mx[i]=max(mx[ls],mx[rs]);
}
void add(int u,int v){
    vv[e]=v;nxt[e]=fst[u]; fst[u]=e++;
}
map<int,int>mp;
int main(){
    //ree;
    int T;sf("%d",&T);
    while(T--){
        mem(fst,-1);e=0;
        mem(mx,-1);
        mp.clear();
        sf("%d%d",&n,&m);
        for(int i=2;i<=n;++i){
            int u,x,y;sf("%d%d%d",&u,&x,&y);
            add(u+1,i);
            a[i].id=i;a[i].x=x;a[i].y=y;
            mp[y]=i;
        }
        col=0;
        dfs(1);
        a[1].id=1;a[1].x=-1;
        a[1].y=-1;
        sort(a+1,a+1+n);
        //rep(i,1,n){
            //pf("%d %d %d\n",a[i].id,a[i].x,a[i].y);
            //pf("%d %d\n",st[a[i].id],ed[a[i].id]);
        //}
        for(int i=1;i<=n;++i){
            int idx=a[i].id;
            int tmp=query(st[idx]+1,ed[idx],1,n,1);
            if(tmp==-1)ans[idx]=-1;
            else ans[idx]=mp[tmp];
            update(idx,a[i].y,1,n,1);
        }
        while(m--){
            int x; sf("%d",&x);
            x++;
            if(ans[x]==-1)puts("-1");
            else{ pf("%d\n",ans[x]-1); }
        }
    }
}

还可以分块。。
参考http://www.cnblogs.com/liuweimingcprogram/p/6143099.html
暂时敲不出,细节。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值