GXOI2019 题解

[GXOI/GZOI2019]与或和
按位处理,只有全部是 1 1 1 那么与出来才是 1 1 1,于是问题转换为求全部是 1 的子矩阵个数
对每个点统计它作为左下角的矩阵个数就可以不重不漏,单调栈即可
考虑或,显然有一个 1 就是 1,那么统计全部是 0 的个数减一下即可


#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
	while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
	return cnt * f;
}
typedef long long ll;
cs int N = 1e3 + 5;
int a[N][N], b[N][N];
int n, h[N], sta[N];
cs int Mod = 1e9 + 7;
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(ll &a, ll b){ a += b; if(a >= Mod) a -= Mod; }
ll calc(int typ){
	memset(h, 0, sizeof(h));
	ll sum = 0;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			if(b[i][j] ^ typ) h[j] = 0;
			else ++h[j]; 
		}
		int top = 0; ll ret = 0;
		for(int j = 1; j <= n; j++){
			while(top && h[j] < h[sta[top]]){
				Add(ret, Mod - mul(h[sta[top]] - h[j], sta[top] - sta[top - 1]));
				top--;
			} sta[++top] = j; ret += h[j]; Add(sum, ret);
		}
	} return sum;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			a[i][j] = read();
	ll ret = n * (n + 1) / 2;
	ll Ans1 = 0, Ans2 = 0;
	for(int k = 0; k < 32; k++){
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
				b[i][j] = a[i][j] >> k & 1;
		ll Or = (ret * ret - calc(0) + Mod) % Mod;
		ll And = calc(1);
		Add(Ans1, mul(And, 1 << k));
		Add(Ans2, mul(Or, 1 << k));
	} cout << Ans1 << " " << Ans2;
	return 0;
}


[GXOI/GZOI2019]宝牌一大堆
对于国士无双:
13 种牌暴力枚举哪一个选两个即可
对于小七对:将所有大于等于2张的牌按贡献排序取前 7 个即可
对于 3 ∗ 4 + 2 3*4 + 2 34+2,显然不能直接统计,考虑 d p dp dp
类似麻将 d p dp dp 的套路,维护 i , i + 1 , i + 2 i,i+1,i+2 i,i+1,i+2 用了的个数
i + 1 , i + 2 i+1,i+2 i+1,i+2 可以只枚举到 2,因为 3 张变刻子
d p [ i ] [ x ] [ y ] [ z ] [ k ] [ 0 / 1 ] dp[i][x][y][z][k][0/1] dp[i][x][y][z][k][0/1] 表示 选到 i i i i , i + 1 , i + 2 i,i+1,i+2 i,i+1,i+2 的出现次数,面子的个数,有无雀头的方案数
暴力枚举转移即可

#include<bits/stdc++.h>
#define cs const
using namespace std;
typedef long long ll;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
	while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
	return cnt * f;
}
cs int N = 40;
int a[N]; // 剩余牌数 
int val[N];  // 宝牌
ll ans;
ll dp[N][5][5][3][3][2];
int T;
int c[5][5] = 
{ 
1, 0, 0, 0, 0,
1, 1, 0, 0, 0,
1, 2, 1, 0, 0, 
1, 3, 3, 1, 0, 
1, 4, 6, 4, 1
};

void Mx(ll &a, ll b){ if(a < b) a = b;}
int ps[N] = {1, 9, 10, 18, 19, 27, 28, 29, 30, 31, 32, 33, 34};
void Yolanda(){
	// 枚举哪一个牌选两张 
	for(int i = 0; i < 13; i++){
		ll sum = 1;
		for(int j = 0; j < 13; j++){
			if(j == i) sum *= c[a[ps[j]]][2] * val[ps[j]] * val[ps[j]];
			else sum *= a[ps[j]] * val[ps[j]];
		} ans = max(ans, sum * 13); 
	} 
}

int value[N]; // 七连对   
void FSY(){
	int ret = 0;
	for(int i = 1; i <= 34; i++) if(a[i] >= 2) value[++ret] = c[a[i]][2] * val[i] * val[i];
	if(ret >= 7){
		ll sum = 1;
		sort(value + 1, value + ret + 1);
		for(int i = ret; i > ret - 7; i--) sum = sum * value[i];
		Mx(ans, sum * 7);
	}
}

bool tail[N];
void DP(){
	dp[1][0][0][0][0][0] = 1;
	for(int i = 1; i <= 34; i++){
		for(int j = 0; j <= 4; j++){ // j 个面子 
			for(int k = 0; k <= 4; k++){ // i 用了多少  
				for(int l = 0; l <= 2; l++){
					for(int r = 0; r <= 2; r++){
						ll *x = dp[i][j][k][l][r];
						if(!x[0] && !x[1]) continue;
						
						if(a[i] - k >= 2){ // 雀头  
							Mx(dp[i][j][k + 2][l][r][1], x[0] / c[a[i]][k] * c[a[i]][k + 2] * val[i] * val[i]) ;
						}
						
						if(j < 4){
						if(a[i] - k >= 3){ // 刻子  
							for(int t = 0; t < 2; t++)
							Mx(dp[i][j + 1][k + 3][l][r][t], x[t] / c[a[i]][k] * c[a[i]][k + 3] * (val[i]*val[i]*val[i]));
						}
						if((!tail[i]) && a[i] - k > 0 && a[i + 1] - l > 0 && a[i + 2] - r > 0 && (l^2) && (r^2)){
							// 顺子  
							for(int t = 0; t < 2; t++){
								Mx(dp[i][j + 1][k + 1][l + 1][r + 1][t], 
								x[t] / c[a[i]][k] * c[a[i]][k+1] * val[i] 
								/ c[a[i + 1]][l] * c[a[i + 1]][l + 1] * val[i + 1] 
								/ c[a[i + 2]][r] * c[a[i + 2]][r + 1] * val[i + 2] 
								);
							}
						}
						}
						
						Mx(dp[i + 1][j][l][r][0][0], x[0]);
						Mx(dp[i + 1][j][l][r][0][1], x[1]);
						if(j == 4) Mx(ans, x[1]); 
					}
				} 
			} 
		}
	}
} 
void Solve(){
	tail[8] = tail[9] = tail[17] = tail[18] = tail[26] = tail[27] = 
	tail[28] = tail[29] = tail[30] = tail[31] = tail[32] = tail[33] = tail[34] = 1;
	while(1){
		char c[3]; scanf("%s", c);
		if(c[0] == '0') break;
		if(c[1] == 'm') a[c[0] - '0']--;
		if(c[1] == 's') a[c[0] - '0' + 9]--;
		if(c[1] == 'p') a[c[0] - '0' + 18]--;
		if(c[0] == 'E') a[28]--;
		if(c[0] == 'S') a[29]--;
		if(c[0] == 'W') a[30]--;
		if(c[0] == 'N') a[31]--;
		if(c[0] == 'Z') a[32]--;
		if(c[0] == 'B') a[33]--;
		if(c[0] == 'F') a[34]--; 
	}
	while(1){
		char c[3]; scanf("%s", c);
		if(c[0] == '0') break;
		if(c[1] == 'm') val[c[0] - '0'] = 2;
		if(c[1] == 's') val[c[0] - '0' + 9] = 2;
		if(c[1] == 'p') val[c[0] - '0' + 18] = 2;
		if(c[0] == 'E') val[28] = 2;
		if(c[0] == 'S') val[29] = 2;
		if(c[0] == 'W') val[30] = 2;
		if(c[0] == 'N') val[31] = 2;
		if(c[0] == 'Z') val[32] = 2;
		if(c[0] == 'B') val[33] = 2;
		if(c[0] == 'F') val[34] = 2; 
	}
	Yolanda(); // 国士无双  
	FSY(); // 七连对  
	DP(); // 3 * 4 + 2
	cout << ans << '\n';
}
void Init(){
	ans = 0;
	for(int i = 1; i <= 34; i++) a[i] = 4, val[i] = 1;
	memset(dp, 0, sizeof(dp));
} 
int main(){
	T = read();
	while(T--) Init(), Solve();
	return 0;
} 

[GXOI/GZOI2019]特技飞行
组合题,由于保证交点数 ≤ 5 e 5 \le 5e5 5e5 ,暴力求出,离散化,坐标选择,扫描线
考虑第一个问,显然最大最小取到的时候 a , b a,b a,b 的个数取到端点
最大的时候,发现可以全部交换,次数为逆序对个数
最小的时候,发现每一个置换必须换 l e n − 1 len-1 len1 次,个数是 n − 置 换 数 n-置换数 n

#include<bits/stdc++.h>
#define cs const
using namespace std;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
	while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
	return cnt * f;
}
typedef long long ll;
typedef long double ld;
cs int N = 1e5 + 5, M = 5e5 + 5, K = 7e5 + 5;
int n, k; ll a, b, c;
int Xs, Xe;
int y[N][2], tp[N];
bool cmp(int a, int b){ return y[a][1] < y[b][1];}
struct P{
	ld x, y; 
	P(ld _x = 0, ld _y = 0){ x = _x, y = _y; }
	P operator + (cs P &a){ return P(x+a.x, y+a.y); }
	P operator - (cs P &a){ return P(x-a.x, y-a.y); }
	P operator * (ld k){ return P(x * k, y * k);}
}p[M], q[N]; int ret;
struct Line{ P a, b; }L[N];
P Getpos(Line u, Line v){
	ld d1 = u.a.y - v.a.y, d2 = u.b.y - v.b.y;
	if(d1 < 0) d1 = -d1; if(d2 < 0) d2 = -d2;
	ld k = 1.0 * d1 / (d1 + d2);
	return u.a + ((u.b - u.a) * k);
} 
struct node{ 
	int id, h; 
	node(int i = 0, int _h = 0){ id = i; h = _h; }
	bool operator < (cs node &a) cs{ return h < a.h;}
};
multiset<node> S;
typedef multiset<node>::iterator Int;
ll ans1, ans2;
int fa[N];
int find(int x){ return x == fa[x] ? x : fa[x] = find(fa[x]);}
int r[N];
ld Dx[K], Dy[K]; int sx, sy;
struct que{ int l, r, op; };
vector<que> v[K]; 
vector<int> u[K]; 
#define pb push_back
struct BIT{
	int c[K]; 
	void add(int x,int v){ for(;x<=sy;x+=x&-x) c[x] += v; }
	int ask(int x){ int ans = 0; for(;x;x-=x&-x) ans += c[x]; return ans; }
}bit;
int Solve(){
	ll sum = 0;
	for(int i = 1; i <= ret; i++){
		ld x = p[i].x, y = p[i].y;
		p[i].x = x + y; p[i].y = x - y;
		Dx[++sx] = p[i].x;
		Dy[++sy] = p[i].y;
	}
	for(int i = 1; i <= k; i++){
		Dx[++sx] = q[i].x - r[i];
		Dx[++sx] = q[i].x + r[i];
		Dy[++sy] = q[i].y - r[i];
		Dy[++sy] = q[i].y + r[i];
	} 
	sort(Dx + 1, Dx + sx + 1);
	sort(Dy + 1, Dy + sy + 1); 
	sx = unique(Dx + 1, Dx + sx + 1) - (Dx + 1);
	sy = unique(Dy + 1, Dy + sy + 1) - (Dy + 1);
	for(int i = 1; i <= ret; i++){
		int x = lower_bound(Dx + 1, Dx + sx + 1, p[i].x) - Dx;
		int y = lower_bound(Dy + 1, Dy + sy + 1, p[i].y) - Dy;
		u[x].pb(y); 
	}
	for(int i = 1; i <= k; i++){
		int lx = lower_bound(Dx + 1, Dx + sx + 1, q[i].x - r[i]) - Dx;
		int rx = lower_bound(Dx + 1, Dx + sx + 1, q[i].x + r[i]) - Dx;
		int ly = lower_bound(Dy + 1, Dy + sy + 1, q[i].y - r[i]) - Dy;
		int ry = lower_bound(Dy + 1, Dy + sy + 1, q[i].y + r[i]) - Dy;
		v[lx].pb((que){ly, ry, 1});
		v[rx + 1].pb((que){ly, ry, -1});
	}
	for(int i = 1; i <= sx; i++){
		for(int j = 0; j < v[i].size(); j++){
			que nx = v[i][j];
			bit.add(nx.l, nx.op);
			bit.add(nx.r + 1, - nx.op);
		}
		for(int j = 0; j < u[i].size(); j++) sum += bit.ask(u[i][j]) > 0;
	} return sum;
}

int main(){
	n = read(), a = read(), b = read(), c = read(), Xs = read(), Xe = read();
	for(int i = 1; i <= n; i++) fa[i] = i;
	for(int i = 1; i <= n; i++) y[i][0] = read();
	for(int i = 1; i <= n; i++) y[i][1] = read(), tp[i] = i;
	sort(tp + 1, tp + n + 1, cmp);
	for(int i = 1; i <= n; i++){
		int fx = find(i), fy = find(tp[i]);
		if(fx ^ fy) fa[fx] = fy;
	}
	for(int i = 1; i <= n; i++) L[i] = (Line){P(Xs, y[i][0]), P(Xe, y[i][1])};
	for(int i = 1; i <= n; i++){
		Int it = S.lower_bound(node(i, y[i][1]));
		for(;it != S.end(); it++){
			p[++ret] = Getpos(L[it->id], L[i]);
		} S.insert(node(i, y[i][1]));
	}
	ans1 = ret * a;
	int cnt = 0;
	for(int i = 1; i <= n; i++) cnt += (find(i) == i);
	ans2 = (n - cnt) * a + (ret - (n - cnt)) * b;
	k = read();
	for(int i = 1; i <= k; i++){
		int x = read(), y = read(); r[i] = read();
		q[i] = P(x + y, x - y);
	} ll sum = 1ll * Solve() * c; 
	if(ans1 > ans2) swap(ans1, ans2);
	cout << ans1 + sum << " " << ans2 + sum;
	return 0;
} 

[GXOI/GZOI2019]逼死强迫症
有一种做法是暴力枚举两个1块的起始和结束位置,显然中间只有 2 种可能,两边是斐波那契拼起来的
考虑递推,令 f i f_i fi 为斐波那契数列, F i F_i Fi 为长度为 i i i 的答案
首先当前点可以由前两个,放两个横或者放一个竖转移过来
F i = F i − 1 + F i − 2 F_i=F_{i-1}+F_{i-2} Fi=Fi1+Fi2
考虑当前点作为一个1的右端点的新增贡献
枚举左端点
F i = 2 ∗ ∑ j = 1 i − 3 f j F_i=2*\sum_{j=1}^{i-3}f_j Fi=2j=1i3fj
s i = ∑ j = 1 i f j s_i = \sum_{j=1}^{i}f_j si=j=1ifj
那么有 F i = F i − 1 + F i − 2 + s i − 3 ∗ 2 = F i − 1 + F i − 2 + 2 ∗ f i − 1 − 2 F_i=F_{i-1}+F_{i-2}+s_{i-3}*2=F_{i-1}+F_{i-2}+2*f_{i-1}-2 Fi=Fi1+Fi2+si32=Fi1+Fi2+2fi12
矩阵乘法即可

#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int Mod = 1000000007;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int T, n;
cs int N = 5;
struct matrix{
	int a[N][N];
	matrix(){ memset(a, 0, sizeof(a)); }
	matrix operator * (cs matrix &A){
		matrix B; for(int i = 0; i < N; i++)
			for(int j = 0; j < N; j++) for(int k = 0; k < N; k++)
				B.a[i][j] = add(B.a[i][j], mul(a[i][k], A.a[k][j]));
		return B;
	}
}I, TR, ST;
matrix power(matrix A, int b){
	matrix ans = I; for(;b;b>>=1, A=A*A) if(b&1) ans = ans*A; return ans;
}
int main(){
	scanf("%d", &T);
	TR.a[0][0] = 1; TR.a[0][1] = 1;
	TR.a[1][0] = 1;
	TR.a[2][0] = 2; TR.a[2][2] = 1; TR.a[2][3] = 1;
	TR.a[3][2] = 1;
	TR.a[4][0] = Mod-2; TR.a[4][4] = 1;
	ST.a[0][0] = 2; ST.a[0][1] = 0; ST.a[0][2] = 3; ST.a[0][3] = 2; ST.a[0][4] = 1;
	for(int i = 0; i < N; i++) I.a[i][i] = 1;
	while(T--){
		scanf("%d", &n);
		if(n <= 2){ puts("0"); continue; }
		matrix A = TR, B = ST;
		B = B * power(A, n - 3); 
		cout << B.a[0][0] << '\n';
	} return 0;
}

[GXOI/GZOI2019]旅行者
D i j s k t r a Dijsktra Dijsktra 染色即可,枚举连接两个染色块的边更新答案

#include<bits/stdc++.h>
#define N 100050
#define M 500050
#define LL long long
#define inf 10000000000000000
using namespace std;
int read(){
	int cnt = 0; char ch = 0;
	while(!isdigit(ch)) ch = getchar();
	while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
	return cnt;
}
int first[N], nxt[M], to[M], w[M], tot;
void add(int x, int y, int z){
	nxt[++tot] = first[x], first[x] = tot;
	to[tot] = y, w[tot] = z;
}
int T, n, m, k, a[N];
struct Node{ int x, y, z;} E[M];
LL dis[N][2]; int col[N][2];
void Dijsktra(int id){
	priority_queue<pair<int, int> > q;
	for(int i=1; i<=n; i++) dis[i][id] = inf, col[i][id] = 0;
	for(int i=1; i<=k; i++){
		col[a[i]][id] = a[i], dis[a[i]][id] = 0;
		q.push(make_pair(-dis[a[i]][id], a[i])); 
	} 
	while(!q.empty()){
		int x = q.top().second; q.pop();
		for(int i=first[x];i;i=nxt[i]){
			int t = to[i]; 
			if(dis[t][id] > dis[x][id] + w[i]){
				dis[t][id] = dis[x][id] + w[i];
				col[t][id] = col[x][id];
				q.push(make_pair(-dis[t][id], t));
			}
		}
	}
	
}
int main(){
	T = read();
	while(T--){
		n = read(), m = read(), k = read();
		for(int i=1; i<=n; i++) first[i] = 0; tot = 0;
		for(int i=1; i<=m; i++){
			int x = read(), y = read(), z = read();
			if(x ^ y) add(x, y, z); E[i] = (Node){x, y, z};
		}
		for(int i=1; i<=k; i++) a[i] = read();
		Dijsktra(0);
		for(int i=1; i<=n; i++) first[i] = 0; tot = 0;
		for(int i=1; i<=m; i++){
			if(E[i].y ^ E[i].x) add(E[i].y, E[i].x, E[i].z);
		}
		Dijsktra(1);
		LL ans = inf;
		for(int i=1; i<=m; i++){
			int x = E[i].x, y = E[i].y, z = E[i].z;
			if(col[x][0] && col[y][1] && col[x][0] != col[y][1]) 
				ans = min(ans, dis[x][0] + dis[y][1] + (LL)z);
		} printf("%lld\n",ans);
	} return 0;
}

[GXOI/GZOI2019]旧词
L C A LCA LCA 那道题一样
考虑到 d e p [ l c a ( x , y ) ] k = ( d e p [ l c a ( x , y ) ] k − ( d e p [ l c a ( x , y ) ] − 1 ) k ) + ( ( d e p [ l c a ( x , y ) ] − 1 ) k − ( d e p [ l c a ( x , y ) ] − 2 ) k ) + . . . dep[lca(x,y)]^k=(dep[lca(x,y)]^k-(dep[lca(x,y)]-1)^k)+((dep[lca(x,y)]-1)^k-(dep[lca(x,y)]-2)^k)+... dep[lca(x,y)]k=(dep[lca(x,y)]k(dep[lca(x,y)]1)k)+((dep[lca(x,y)]1)k(dep[lca(x,y)]2)k)+...
而一个点恒定加的一个常数 a x a_x ax,树剖,线段树,预处理 s u m ( a x ) sum(a_x) sum(ax) 就可以 p u s h d o w n pushdown pushdown

#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int Mod = 998244353;
int read(){
	int cnt = 0, f = 1; char ch = 0;
	while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
	while(isdigit(ch)) cnt = cnt*10 + (ch - '0'), ch = getchar();
	return cnt * f;
}
cs int N = 5e4 + 5;
int n, m, k;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a, b); }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1, a=mul(a,a)) if(b&1) ans=mul(ans,a); return ans; }
vector<int> v[N];
int fa[N], dep[N], top[N], siz[N], son[N], in[N], sign;
int a[N], pw[N];
typedef pair<int, int> pi;
#define mp make_pair
int ans[N];
vector<pi> q[N];

namespace seg{
	int sum[N << 2], val[N << 2], tg[N << 2];
	#define mid ((l+r)>>1)
	void ins(int x, int l, int r, int p, int v){
		Add(sum[x],v); if(l == r) return; 
		if(p <= mid) ins(x<<1, l, mid, p, v); else ins(x<<1|1, mid+1, r, p, v);
	}
	void pushup(int x){ val[x] = add(val[x<<1], val[x<<1|1]);}
	void pushnow(int x, int v){ Add(val[x], mul(v, sum[x])); Add(tg[x], v); }
	void pushdown(int x){ if(tg[x]) pushnow(x<<1, tg[x]), pushnow(x<<1|1, tg[x]), tg[x] = 0; }
	void modify(int x, int l, int r, int L, int R, int v){
		if(L<=l && r<=R){ pushnow(x, v); return; }
		pushdown(x);
		if(L<=mid) modify(x<<1, l, mid, L, R, v);
		if(R>mid) modify(x<<1|1, mid+1, r, L, R, v);
		pushup(x);
	}
	int query(int x, int l, int r, int L, int R){
		if(L<=l && r<=R) return val[x]; pushdown(x); int ans = 0;
		if(L<=mid) Add(ans, query(x<<1, l, mid, L, R));
		if(R>mid) Add(ans, query(x<<1|1, mid+1, r, L, R));
		return ans;
	}
}
void dfs(int u){
	siz[u] = 1; 
	for(int i = 0; i < v[u].size(); i++){
		int t = v[u][i]; 
		dep[t] = dep[u] + 1; fa[t] = u;
		a[t] = add(pw[dep[t]], Mod - pw[dep[u]]);
		dfs(t); siz[u] += siz[t];
		if(siz[son[u]] > siz[t]) son[u] = t;
	}
}
void dfs2(int u, int tp){
	top[u] = tp; in[u] = ++sign; seg::ins(1,1,n,in[u],a[u]);
	if(son[u]) dfs2(son[u], tp);
	for(int i = 0; i < v[u].size(); i++) if(v[u][i]^son[u]) dfs2(v[u][i], v[u][i]);
}
void modify(int x){ while(x){ seg::modify(1,1,n,in[top[x]],in[x],1); x=fa[top[x]]; } }
int ask(int x){ int ans=0; while(x){ Add(ans,seg::query(1,1,n,in[top[x]],in[x])); x=fa[top[x]];} return ans; }
int main(){
	n = read(), m = read(), k = read();
	for(int i = 1; i <= n; i++) pw[i] = ksm(i, k);
	for(int i = 2; i <= n; i++){
		int x = read(); v[x].push_back(i);
	} dep[1] = a[1] = 1; dfs(1); dfs2(1, 1);
	for(int i = 1; i <= m; i++){
		int x = read(), y = read();
		q[x].push_back(mp(y, i));
	}
	for(int i = 1; i <= n; i++){
		modify(i); 
		for(int j = 0; j < q[i].size(); j++){
			int x = q[i][j].first; 
			ans[q[i][j].second] = ask(x);
		}
	} 
	for(int i = 1; i <= m; i++) cout << ans[i] << '\n';
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值