编号在l~r的点有r-l+1个,因为原图是一棵树,没有环,所以每多一条边,连通块就少1,所以我们只要求出顶点均在l~r的边的数目,最后用点数减一下就好
这个问题怎么处理呢,我刚开始想的是把所有的边抽象成平面上的一个点,横纵坐标分别代表两个端点编号,这样l~r之间的查询相当于查询一个正方形区域内有多少个点,但这个好像不能离散化,用什么二维数据结构也没用
考虑一种离线做法:将询问按照右端点排序,然后从大到小处理,我们用树状数组维护所有查询的左端点,假设当前我在处理右端点为i的询问,那我就要保证有大于i的端点的边已经被删掉了,这样我就可以直接查询a[l]~i中有多少个点
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <utility>
#include <cctype>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#define LL long long
#define LB long double
#define x first
#define y second
#define Pair pair<int,int>
#define pb push_back
#define pf push_front
#define mp make_pair
#define LOWBIT(x) x & (-x)
using namespace std;
const int MOD=1e9+9;
const LL LINF=2e16;
const int INF=2e9;
const int magic=348;
const double eps=1e-10;
const double pi=3.14159265;
inline int getint()
{
char ch;int res;bool f;
while (!isdigit(ch=getchar()) && ch!='-') {}
if (ch=='-') f=false,res=0; else f=true,res=ch-'0';
while (isdigit(ch=getchar())) res=res*10+ch-'0';
return f?res:-res;
}
int n,qnum;
Pair edge[200048];
struct Query
{
int left,right;
int ind;
}q[200048];
namespace BIT
{
int c[200048];
inline void init() {for (register int i=1;i<=n;i++) c[i]=0;}
inline void update(int x,int delta)
{
while (x<=n)
{
c[x]+=delta;
x+=LOWBIT(x);
}
}
inline int query(int x)
{
int res=0;
while (x)
{
res+=c[x];
x-=LOWBIT(x);
}
return res;
}
inline int calc(int left,int right) {return query(right)-query(left-1);}
}
vector<int> Edge[200048];
vector<Pair> que[200048];
int ans[200048];
inline void Clear()
{
int i;
for (i=1;i<=n;i++) Edge[i].clear();
for (i=1;i<=n;i++) que[i].clear();
}
int main ()
{
int ca,i,j,x,y;ca=getint();
while (ca--)
{
n=getint();qnum=getint();
Clear();
for (i=1;i<=n-1;i++)
{
x=getint();y=getint();if (x>y) swap(x,y);
edge[i]=mp(x,y);
Edge[y].pb(x);
}
for (i=1;i<=qnum;i++)
{
q[i].left=getint();q[i].right=getint();q[i].ind=i;
que[q[i].right].pb(mp(q[i].left,i));
}
BIT::init();
for (i=1;i<=n-1;i++) BIT::update(edge[i].x,1);
for (i=n;i;i--)
{
if (i!=n)
for (j=0;j<int(Edge[i+1].size());j++)
BIT::update(Edge[i+1][j],-1);
for (j=0;j<int(que[i].size());j++)
{
int res=BIT::calc(que[i][j].x,i);
ans[que[i][j].y]=(i-que[i][j].x+1)-res;
}
}
for (i=1;i<=qnum;i++) printf("%d\n",ans[i]);
}
return 0;
}