题目
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();
}
}