CodeForces 173E Camping Groups 离线线段树 树状数组

Camping Groups

题目连接:

http://codeforces.com/problemset/problem/173/E

Description

A club wants to take its members camping. In order to organize the event better the club directors decided to partition the members into several groups.

Club member i has a responsibility value ri and an age value ai. A group is a non-empty subset of club members with one member known as group leader. A group leader should be one of the most responsible members of the group (his responsibility value is not less than responsibility of any other group member) and his age absolute difference with any other group member should not exceed k.

Some club members are friends and want to be in the same group. They also like their group to be as large as possible. Now you should write a program that answers a series of questions like "What's the largest size of a group containing club member x and club member y?". It's possible for x or y to be the group leader.

Input

The first line contains two integers n and k (2 ≤ n ≤ 105, 0 ≤ k ≤ 109) — the number of club members and the age restriction for one group.

The next line contains integer numbers r1, r2, ..., rn (1 ≤ ri ≤ 109) separated by space: ri denotes the i-th club member's responsibility. In the same way there are integers a1, a2, ..., an (1 ≤ ai ≤ 109) in the third line: ai denotes the i-th club member's age.

The next line contains an integer q denoting the number of questions that you should answer (1 ≤ q ≤ 105). The next q lines describe the questions. Each line contains two space-separated integers xi and yi (1 ≤ xi, yi ≤ n, xi ≠ yi) — the indices of the club members that should end up in the same group.

Output

For each question print the maximum size of the group in a line. If making such a group is impossible print -1 instead.

Sample Input

5 1

1 5 4 1 2

4 4 3 2 2

4

5 3

2 3

2 5

4 1

Sample Output

4

3

-1

4

Hint

题意

给你n个人,每个人都有两个属性点,ri和ai,表示这个人的领导值和年龄

然后可以让一个人当领导,他可以领导所有领导值小于等于他的人,年龄和他的之差不超过k的人

然后Q次询问

问你x,y所能够在的最大团队的大小是多少

题解:

离散化是显然的

首先,我们离线树状数组,按照领导值从小到大排序之后,年龄当成坐标,去维护每一个人当领导的时候能够领导多少个人

然后我们再把所有询问全部读入,把询问和每个人都扔到一个vector里面,按照领导值从大到小排序,这样显然先更新的点一定能够统领后面的人

然后再离线去维护询问就好了

代码

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

struct node
{
    int x,y,id;
    int flag;
    int ans;
}p[1300000],p2[1300000],p3[1300000];
int n,k;
vector<int> V;
map<int,int> H;
typedef int SgTreeDataType;
struct treenode
{
  int L , R  ;
  SgTreeDataType sum , lazy;
};
struct Question
{
    int l,r,lead,flag,ans;
};
vector<Question>T;
treenode tree[2300000];


inline void push_up(int o)
{
    tree[o].sum = max(tree[2*o].sum , tree[2*o+1].sum);
}

inline void build_tree(int L , int R , int o)
{
    tree[o].L = L , tree[o].R = R,tree[o].sum = tree[o].lazy = 0;
    if (R > L)
    {
        int mid = (L+R) >> 1;
        build_tree(L,mid,o*2);
        build_tree(mid+1,R,o*2+1);
    }
}

inline void updata(int QL,int QR,SgTreeDataType v,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if (QL <= L && R <= QR) tree[o].sum = max(tree[o].sum,v);
    else
    {
        int mid = (L+R)>>1;
        if (QL <= mid) updata(QL,QR,v,o*2);
        if (QR >  mid) updata(QL,QR,v,o*2+1);
        push_up(o);
    }
}

inline SgTreeDataType query(int QL,int QR,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if (QL <= L && R <= QR) return tree[o].sum;
    else
    {
        int mid = (L+R)>>1;
        SgTreeDataType res = 0;
        if (QL <= mid) res = max(res,query(QL,QR,2*o));
        if (QR > mid) res = max(res,query(QL,QR,2*o+1));
        push_up(o);
        return res;
    }
}

struct Bit
{
    vector<int> a;
    int sz;
    void init(int n)
    {
        sz=n;
        for(int i=1;i<=n+5;i++)
            a.push_back(0);
    }
    int lowbit(int x)
    {
        return x&(-x);
    }
    int query(int x)
    {
        if(x==0)return 0;
        int ans = 0;
        for(;x;x-=lowbit(x))ans+=a[x];
        return ans;
    }
    void updata(int x,int v)
    {
        if(x==0)return;
        for(;x<sz;x+=lowbit(x))
            a[x]+=v;
    }
}bit;
bool cmp(node a,node b)
{
    if(a.x==b.x)return a.flag>b.flag;
    return a.x<b.x;
}
bool cmp2(Question a,Question b)
{
    if(a.lead == b.lead)
        return a.flag<b.flag;
    return a.lead>b.lead;
}
int ans[1300000];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i].x);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&p[i].y);
        V.push_back(p[i].y);
        V.push_back(p[i].y-k);
        V.push_back(p[i].y+k);
        p[i].id=i;
        p[i].flag=1;
    }

    sort(V.begin(),V.end());
    V.erase(unique(V.begin(),V.end()),V.end());
    for(int i=0;i<V.size();i++)
        H[V[i]]=i+1;

    for(int i=1;i<=n;i++)
        p2[i]=p[i];

    for(int i=1;i<=n;i++)
    {
        p2[i+n]=p[i];
        p2[i+n].flag=-1;
    }

    sort(p2+1,p2+2*n+1,cmp);

    bit.init(10*n);

    for(int i=1;i<=2*n;i++)
    {
        if(p2[i].flag==1)
            bit.updata(H[p2[i].y],1);
        else
        {
            int sum = bit.query(H[p2[i].y+k])-bit.query(H[p2[i].y-k]-1);
            p[p2[i].id].ans=sum;
        }
    }

    for(int i=1;i<=n;i++)
    {
        Question now;
        now.l = p[i].y;
        now.r = p[i].y;
        now.lead = p[i].x;
        now.ans = p[i].ans;
        now.flag = 0;
        T.push_back(now);
    }

    int q;scanf("%d",&q);

    for(int i=1;i<=q;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(p[x].y>p[y].y)swap(x,y);
        Question now;
        now.l = p[y].y-k;
        now.r = p[x].y+k;
        now.lead = max(p[x].x,p[y].x);
        now.ans = 0;
        now.flag = i;
        T.push_back(now);
    }

    sort(T.begin(),T.end(),cmp2);
    build_tree(1,5*n+5*q,1);

    for(int i=0;i<T.size();i++)
    {
        if(T[i].flag==0)
            updata(H[T[i].l],H[T[i].r],T[i].ans,1);
        else
        {
            if(T[i].l>T[i].r)ans[T[i].flag]=-1;
            else{
                int ans1 = query(H[T[i].l],H[T[i].r],1);
                ans[T[i].flag] = ans1;
            }
        }
    }
    for(int i=1;i<=q;i++)
    {
        if(ans[i]<2)
            printf("-1\n");
        else
            printf("%d\n",ans[i]);
    }
}

转载于:https://www.cnblogs.com/qscqesze/p/5146257.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值