E - Yet Another Tree Query Problem ZOJ - 4008

题目

Yet Another Tree Query Problem
Time Limit: 3 Seconds      Memory Limit: 65536 KB
Given a tree with  vertices, which are numbered by integers from 1 to , there are  queries.

Each query can be described with two integers  and . A vertex  is good, if and only if ; An edge  is good, if and only if both  and  are good. Please print the number of connected components consist of all the good vertices and the good edges.

Input
There are multiple test cases. The first line of the input is an integer  (about 5), indicating the number of test cases. For each test case:

The first line contains two integers  and  (), indicating the number of vertices and the number of queries.

The following  lines each contains two integers  and  (), indicating an edge connecting vertex  and  in the tree.

The following  lines each contains two integers  and  (), indicating a query.

It's guaranteed that the given graph is a tree.

Output
For each query output one line containing one integer, indicating the answer.

Sample Input
2
4 6
1 4
4 3
3 2
1 2
2 3
3 4
1 3
2 4
1 4
3 2
1 3
2 3
1 2
2 3
Sample Output
2
1
1
2
1
1
2
1
Hint
For the six queries in case 1, the connected components are listed as follows:

[1], [2]
[2, 3]
[3, 4]
[1], [2, 3]
[2, 3, 4]
[1, 2, 3, 4]
For the two queries in case 2, the connected components are as follows:

[1], [2]
[2, 3]
Author: WANG, Yuhan
Source: ZOJ Monthly, March 2018
Submit    Status
Copyright @ 2001-2018, Zhejiang University ACM/ICPC Team, All rights reserved.

题目分析:
题目讲的是一颗树,问查询[l,r]区间内,独立的点和边的个数。
这题很巧妙的利用了查询的先后顺序进行答案的排布。

首先要对查询的数组的r侧进行排序,排序后左侧l所在位置标记上1,代表此处的点要换成边。并且要保证r不要超过要查询的范围。
这里写图片描述
比如说,q.l = 1 q.r=4
那么我们需要把
1-4,3-4,2-3,1-2
这里写图片描述
底线代表被标记

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <queue>
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)

#define mset(var,val) memset(var,val,sizeof(var))

#define test(a) cout<<a<<endl
#define test2(a,b) cout<<a<<" "<<b<<endl
#define test3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl
const int mod =1e9+7 ;
typedef long long ll;
using namespace std;
const int MAXN = 2e5+10;
int C[MAXN*4];
int n;
int lowbit(int x){
    return x&(-x);
}
int sum(int x){
    int ret = 0;
    while(x>0){
        ret += C[x]; x-=lowbit(x);
    }
    return ret;
}
void add(int x,int d){
    while(x<=n){
        C[x]+=d;
        x+=lowbit(x);
    }
}
vector<int>g[MAXN];
int ans[MAXN];
struct  node
{
    int u,v;
    int id; 
    bool friend operator < (node a,node b){
        if(a.v == b.v){
            return a.u<b.u;
        }
        return a.v<b.v;
    }
}q[MAXN];
void work(){    
    int Q;
    scdd(n,Q);
    mset(C,0);
    int u,v;
    for(int i =0;i<=n;i++)g[i].clear();
    for(int i =0;i<n-1;i++){
            scdd(u,v);
            if(u>v)swap(u,v);
            g[v].push_back(u);
    }
    for(int i =0;i<Q;i++){
        scdd(u,v);
        q[i].u=u;
        q[i].v=v;
        q[i].id=i;
    }
    sort(q,q+Q);
    int l=1;
    for(int i =0;i<Q;i++){
        while(l<=q[i].v){
            for(int j =0;j<g[l].size();j++){
                v = g[l][j];
                add(v,1);
            }
            l++;
        }
        ans[q[i].id]=(q[i].v-q[i].u+1)-(sum(q[i].v)-sum(q[i].u-1));
    }
    for(int i =0;i<Q;i++){
        printf("%d\n",ans[i]);
    }
}
int main(){
    #ifdef local
        freopen("in.txt","r",stdin);
    #endif
    int  t;
    scd(t);
    while(t--){
        work();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值