Eyjafjalla

Eyjafjalla

https://ac.nowcoder.com/acm/contest/11260/E

= =两个月不学习的fw这两个月来写的第一个题..
简单的来说就是树状数组硬搞...
首先在假如温度区间不在这个范围的点,先做个标记,就不用往上跳,且下面的点也一定不行..
然后就简单的倍增因为符合单调性就跳,跳到最高点然后判断子树中合法的.
简单的说就是在这个温度区间的,然后因为不涉及修改操作,可以树状数组离线按权值排序,左右端点的权值先分开再整合..然后离散化一下dfs序一下就可以通过这个题目了.\

code:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=20;
vector<int>G[N<<2];
int ls[N<<2],id,t[N<<2],x[N<<2],L[N<<2],R[N<<2],c[N<<2],n,num;
int bit(int u)
{
    return u&(-u);
}

void add(int u)
{
    while(u<=num)
    {
        c[u]++;
        u+=bit(u);
    }
}

int qry(int u)
{
    int res=0;
    while(u)
    {
        res+=c[u];
        u-=bit(u);
    }
    return res;
}

int f[N][M],sz[N],idx,S[N];

struct Qry{
    int l,r,wl,wr,id;
}Q[N];

struct cs{
    int w,id;
}a[N];

bool cnp(cs A,cs B)
{
    return A.w<B.w;
}

bool Ans(Qry A,Qry B)
{
    return A.id<B.id;
}

struct Res{
    int w,l,r,id,op,ans,f;
}ask[N<<2];

bool cmmp(Res A,Res B)
{
    return A.w<B.w;
}

bool cnnp(Res A,Res B)
{
    if(A.id==B.id)  return A.op>B.op;
    else            return A.id<B.id;
}

void init(int u,int fa)
{
    f[u][0]=fa;sz[u]=1;S[u]=++idx;
    for(int i=1;i<=19;i++)
        f[u][i]=f[f[u][i-1]][i-1];
    for(int v:G[u])
    {
        if(v==fa)   continue;
        init(v,u);
        sz[u]+=sz[v];
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&t[i]);
        ls[++id]=t[i];
    }
    int q;
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d%d",&x[i],&L[i],&R[i]);
        ls[++id]=L[i];
        ls[++id]=R[i];
    }
    sort(ls+1,ls+1+id);
    num=unique(ls+1,ls+1+id)-ls-1;
    for(int i=1;i<=n;i++)
    {
        t[i]=lower_bound(ls+1,ls+1+num,t[i])-ls;
        a[i].w=t[i];
        a[i].id=i;
    }
    for(int i=1;i<=q;i++)
    {
        L[i]=lower_bound(ls+1,ls+1+num,L[i])-ls;
        R[i]=lower_bound(ls+1,ls+1+num,R[i])-ls;
    }
    t[0]=1e9;
    init(1,0);
    int dd=0;
    for(int i=1;i<=q;i++)
    {
        bool fl=false;
        //找到每个点的节点在哪.
        int u=x[i];
        Q[i].id=i;
        Q[i].wl=L[i];
        Q[i].wr=R[i];
        if(t[u]>R[i]||t[u]<L[i])    fl=true;
        for(int j=19;j>=0;j--)
        {
            if(t[f[u][j]]<=R[i])    u=f[u][j];
        }
        Q[i].l=S[u];
        Q[i].r=S[u]+sz[u]-1;
        ask[++dd].id=i;
        ask[dd].op=0;
        ask[dd].l=Q[i].l;
        ask[dd].r=Q[i].r;
        ask[dd].w=L[i]-1;
        if(fl)  ask[dd].f=1;
        else    ask[dd].f=0;
        ask[++dd].id=i;
        ask[dd].op=1;
        ask[dd].l=Q[i].l;
        ask[dd].r=Q[i].r;
        ask[dd].w=R[i];
        if(fl)  ask[dd].f=1;
        else    ask[dd].f=0;
    }
    sort(a+1,a+1+n,cnp);
    sort(ask+1,ask+1+dd,cmmp);
    int l=1;
    for(int i=1;i<=dd;i++)
    {
        while(l<=n&&a[l].w<=ask[i].w)    add(S[a[l].id]),l++;
        if(ask[i].f)     ask[i].ans=0;
        else             ask[i].ans=qry(ask[i].r)-qry(ask[i].l-1);
    }
    sort(ask+1,ask+1+dd,cnnp);
    for(int i=1;i<=dd;i+=2)
    {
        printf("%d\n",ask[i].ans-ask[i+1].ans);
    }
    return 0;
}
lpt的小屋 文章被收录于专栏

我想要一份甜甜的爱情

全部评论

相关推荐

10-27 17:26
东北大学 Java
点赞 评论 收藏
分享
尊嘟假嘟点击就送:加v细说,问题很大
点赞 评论 收藏
分享
点赞 评论 收藏
分享
4 收藏 评论
分享
牛客网
牛客企业服务