首页 > 其他分享 >P7394 「TOCO Round 1」History

P7394 「TOCO Round 1」History

时间:2024-10-10 09:33:06浏览次数:1  
标签:二分 dep TOCO int P7394 fa lst maxN History

操作树加二分,目前题解区没有这种做法。

发现操作一可逆,可以用操作树,操作三解决。

操作一单点修改没什么好说的。

接下来看操作二。令 \(fa_{x,k}\) 为 \(x\) 的 \(k\) 级祖先。

发现对于每个询问中,如果 \(y\) 为奇数那么答案为 \(0\)。如果 \(y\) 为偶数,那么答案就是 \(fa_{x,y/2}\) 的 \(y/2\) 级儿子的开灯的个数减 \(fa_{x,y/2-1}\) 的 \(y/2-1\) 级儿子的开灯的个数。

具体实现方法就是先对这棵树跑出每个点的 bfs 序和 dfs 序,记树的第 \(i\) 层最大的 bfs 序为 \(lst_i\)。所有深度为 \(d\) 的点的 bfs 序都在 \([lst_{d-1}+1,lst_d]\),在这个区间二分。

举个例子:

现在的询问 \(x=5,y=4\),那么 \(fa_{x,y/2}=2\),二分时如果二分出的点在以 \(fa_{x,y/2}\) 为根的子树内,视想要哪边的端点移动二分区间。如果不在这棵子树内,则与 \(fa_{x,y/2}\) 的 dfs 序比较。如果小,二分区间右移;如果大,二分区间左移。例如,目前二分到了 \(11\) 号节点,它的 dfs 序小于 \(2\) 的 dfs 序,那么二分区间右移。

最终答案为红色区间中的开灯个数减蓝色中的开灯个数。

用支持单点修改,区间求和的数据结构(例如树状数组)维护下就好了。

复杂度 \(O(n\log n)\)。

#include <bits/stdc++.h>

using namespace std;

int read() {
    int s = 0, w = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-')
            w = -w;
        c = getchar();
    }
    while (isdigit(c)) {
        s = s * 10 + c - 48;
        c = getchar();
    }
    return s * w;
}
void pr(int x) {
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        pr(x / 10);
    putchar(x % 10 + 48);
}
#define end_ putchar('\n')
#define spc_ putchar(' ')

const int maxN = 1e5 + 7;

int n, m;

vector<int> E[maxN];

int bfn[maxN], dfn[maxN], tot;
int dep[maxN], siz[maxN], lst[maxN], rk[maxN];

int fa[25][maxN];

void dfs(int x, int f) {
	dep[x] = dep[f] + 1;
	siz[x] = 1;
	dfn[x] = ++tot;
	
	fa[0][x] = f;
	for (int t = 1; t <= 20; t++)
		fa[t][x] = fa[t - 1][fa[t - 1][x]];
		
	for (int to : E[x])
		if (to != f) {
			dfs(to, x);
			siz[x] += siz[to];
		}
}
void bfs() {
	tot = 0;
	queue<int> Q;
	Q.push(1);
	while (!Q.empty()) {
		int f = Q.front();
		Q.pop();
		bfn[f] = ++tot;
		rk[tot] = f;
		for (int to : E[f])
			if (dep[to] > dep[f])
				Q.push(to);
	}
}

int find(int x, int k) {
	for (int i = 0; k; i++, k >>= 1)
		if (k & 1)
			x = fa[i][x];
	return x;
}

int cnt;
struct node {
	int to, x, y, id;
	node(int a, int b) {
		to = a, x = b;
		y = id = -1;
	}
	node(int a, int b, int c, int d) {
		to = a, x = b, y = c, id = d;
	}
};
vector<node> mo[maxN];

int qcnt;
struct ques {
	int x, y, id;
};
vector<ques> q[maxN];
int ans[maxN];

int v[maxN];
int t[maxN];
void add(int x, int v) {
	for (; x <= n; x += x & -x)
		t[x] += v;
}
int ask(int x) {
	int res = 0;
	for (; x > 0; x -= x & -x)
		res += t[x];
	return res;
}

int solve(int x, int y) {
	if (y == 0)
		return v[x];
	if (y & 1)
		return 0;
	y >>= 1;
	
	int f = find(x, y);
	if (!f)
		return 0;
	
	auto erfen = [x](bool ty, int f) {
		int L = lst[dep[x] - 1] + 1, R = lst[dep[x]];
		int ans = -1;
		while (L <= R) {
			int mid = (L + R) >> 1;
			int p = rk[mid];
			if (dfn[f] <= dfn[p] && dfn[p] <= dfn[f] + siz[f] - 1) {
				ans = p;
				if (ty)
					R = mid - 1;
				else
					L = mid + 1;
			}
			else if (dfn[p] < dfn[f])
				L = mid + 1;
			else
				R = mid - 1;
		}
		return ans;
	};
	
	int l = erfen(true, f), r = erfen(false, f);
	int res = ask(bfn[r]) - ask(bfn[l] - 1);
	
	f = find(x, y - 1);
	
	l = erfen(true, f), r = erfen(false, f);
	int tmp = ask(bfn[r]) - ask(bfn[l] - 1);
	
	return res - tmp;
}

void calc(int x) {
	for (auto i : mo[x]) {
		if (i.x != -1 && i.id == -1) {
			if (v[i.x])
				v[i.x] = 0, add(bfn[i.x], -1);
			else
				v[i.x] = 1, add(bfn[i.x], 1);
		}
		if (i.id != -1)
			ans[i.id] = solve(i.x, i.y);
		
		calc(i.to);
		
		if (i.x != -1 && i.id == -1) {
			if (v[i.x])
				v[i.x] = 0, add(bfn[i.x], -1);
			else
				v[i.x] = 1, add(bfn[i.x], 1);
		}
	}
}

int main() {
	n = read();
	for (int i = 1; i < n; i++) {
		int u = read(), v = read();
		E[u].push_back(v);
		E[v].push_back(u);
	}
	dfs(1, 0);
	bfs();
	for (int i = 1; i <= n; i++)
		lst[dep[i]] = max(lst[dep[i]], bfn[i]);
	
	memset(ans, 255, sizeof(ans));
	
	m = read();
	for (int i = 1; i <= m; i++) {
		int op = read();
		if (op == 1) {
			int x = read();
			mo[cnt].emplace_back(cnt + 1, x);
			++cnt;
		}
		if (op == 2) {
			int x = read(), y = read();
			mo[cnt].emplace_back(cnt + 1, x, y, i);
			++cnt;
		}
		if (op == 3) {
			int x = read();
			mo[x].emplace_back(cnt + 1, -1);
			++cnt;
		}
	}
	
	calc(0);
	
	for (int i = 1; i <= m; i++)
		if (ans[i] != -1)
			pr(ans[i]), end_;
}

标签:二分,dep,TOCO,int,P7394,fa,lst,maxN,History
From: https://www.cnblogs.com/ccxswl/p/18455645

相关文章

  • 发送proxy protocol报文
    V1echo-e"PROXYTCP4192.0.2.1203.0.113.11234580\r\nGET/HTTP/1.0\r\n\r\n"|nc10.0.2.1580000000000000000000000000000008004500..............E.001000613b2d4000400601687f0000017f00.a;-@[email protected].......
  • PPP点对点协议(Point-to-Point Protocol)
      PPP(Point-to-PointProtocol,点对点协议)是一种广泛用于广域网(WAN)连接的链路层协议,常用于通过电话线、光纤或其他物理介质建立点对点的直接连接。PPP主要用于支持IP和IPX等网络层协议,提供了多种功能和扩展,确保稳定、灵活的网络传输。它广泛用于拨号网络、DSL、光纤宽......
  • Delphi10.3关键字自动填充完成AutoComplete
    声明两个全局变量varaStringList:TStringList;//读取关键字aMemoInput:string;//当前已输入项procedureTSearchReplaceDemoForm.FormCreate(Sender:TObject);beginaStringList:=TStringList.Create;aStringList.LoadFromFile('keyWord.txt');//从文件......
  • vue解决history路由模式刷新重定向问题(apache服务器)
    问题:vue文件打包后部署到apache服务器下,vue在history路由模式时,访问www.xx.com/about路径时刷新会导致notfount页面,这是因为www.xx.com/about目录不存在于服务器。解决:apche服务器重写路由到www.xx.com/下。然后刷新可正常访问到about页面apache开启路由重写1、配置文件......
  • WPF behavior InvokeCommndAction PassEventArgsToCommand
    //xaml<ListBoxx:Name="lbx"SelectedIndex="0"ItemsSource="{BindingBooksCollection,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"VirtualizingPanel.IsContainerVirtualizable="Tru......
  • Vue.js入门系列(三十):深入理解独享路由守卫、组件内路由守卫、History模式与Hash模式
    个人名片......
  • 微信小程序报错request:fail -107:net::ERR_SSL_PROTOCOL_ERROR
            最近打算上线一个微信小程序,然后在本地运行,访问后端服务器正常,但是上线服务器后却发现小程序不能连接后端服务器,于是我用微信开发工具真机调试后发现,提示是ssl证书问题,我在本地调试时勾选了不校验合法域名,导致我本地上运行正常        后面我勾选了......
  • ToCom:一次训练随意使用,华为提出通用的ViT标记压缩器 | ECCV 2024
    标记压缩通过减少冗余标记的数量(例如,修剪不重要的标记或合并相似的标记)来加快视觉变换器(ViTs)的训练和推理。然而,当这些方法应用于下游任务时,如果训练和推理阶段的压缩程度不匹配,会导致显著的性能下降,这限制了标记压缩在现成训练模型上的应用。因此提出了标记补偿器(ToCom),以解耦两......
  • 高版本mysql访问出现Client does not support authentication protocol requested by
    访问8.0等高版本数据库报错:Clientdoesnotsupportauthenticationprotocolrequestedbyserver;considerupgradingMySQLclient(客户端不支持服务器请求的身份验证协议;请考虑升级MySQL客户端)这种问题就是你访问的工具身份验证协议过于落后,如果是navicat之类的软件可以考虑......
  • 【Java】已解决:com.alibaba.com.caucho.hessian.io.HessianProtocolException异常
    文章目录一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例服务端代码客户端代码五、注意事项已解决:com.alibaba.com.caucho.hessian.io.HessianProtocolException异常一、分析问题背景在使用Hessian进行远程调用时,开发者有时会遇到com.al......