CodeForces 825G Educational Round #25 G :建树选根大法+O1大法+iostream解绑了还是慢

来源:互联网 发布:淘宝鞋子质量问题范围 编辑:程序博客网 时间:2024/05/31 18:51

题意:给出一棵无向的树(n<=1e6),开始树的所有vertex都是白色的,然后给出q(<=1e6)次询问,询问分为1、2两种:1:将index号节点涂成黑色。2:询问index号节点到所有的小黑点的简单路径中的标号最小的那个点(包括起点和小黑点)。题目保证第一次询问是1类型的。

题解:如果我们随便选取root,那么询问的时候,我们要找到这个点到所有小黑点的路径(LCA),但是这样显然会超时的。所以我们换一种建树姿势。由于第一个询问必然是1类型,那么我们就把第一次询问的那个变黑的点作为root,看一下这样有什么好处:假设我们树上已经有了一些小黑点了,那么当我们遇到2类型询问index的时候,我们考虑index到所有的小黑点的简单路径:首先是root,路径就是index到根,其次考虑非root的小黑点,分成两种情况:1、lca(小黑点,index)==root,那么index到这个小黑点的简单路径是index-root-小黑点。2、lca(index,小黑点)!=root,那么index到小黑点的路径是index-lca-小黑点,而lca必然在index-root的路径上。而因为root是小黑点,所以index-root上的最小值一定会被考虑,而lca-root必然是index-root的一段,所以说index-lca-小黑点这条路可以拆成index-root和root-小黑点。(因为lca-root这条路径必然会被考虑,所以可以把index-lca-小黑点的检测范围拓展一下,对答案毫无影响)。因此我们只需要记录下树上每个vertex到root的路径上所有点标号最小的那一个(先求Deep,然后跑DFS),之后就可以O(1)出答案了。

注意:1、本题强制在线,需要记录last=最后一次2询问的ans,并且每次询问的点的index=(input+last)%n+1。

2、cin、cout慢的出翔,解绑流之后效率依然不足够,乖乖的用scanf/printf吧。

Code:

#include<bits/stdc++.h>using namespace std;#define MAX 1000006#define INF n+1int n,q;vector<int> E[MAX];int minNum[MAX];int que[MAX*5];int deep[MAX];int root;int last = 0;int ans ;void init(){ cin>>n>>q; for (int i=1;i<n;i++){  int u,v;  scanf("%d%d",&u,&v);  E[u].push_back(v);  E[v].push_back(u); } scanf("%d%d",&root,&root); root = root%n+1; ans = root; q--; for (int i=0;i<=n;i++){  minNum[i] = i; }} void initBuild(){ int l =0,r=1; que[1] = root; deep[root] = 1; while (l<r){  l++;  int a = que[l];  for (vector<int>::iterator it = E[a].begin();it!=E[a].end();it++){   if (deep[(*it)]==0){    deep[(*it)] = deep[a]+1;    r++;    que[r] = (*it);   }  } }}void build (){ initBuild(); int l=0,r=1; que[1]=root; minNum[root] = root; while (l<r){  l++;  int a = que[l];  int temp = minNum[a];  for (vector<int>::iterator it = E[a].begin();it!=E[a].end();it++){   if (deep[(*it)]>deep[a]){    minNum[(*it)] = min(temp,minNum[(*it)]);    r++;    que[r] = (*it);   }  } }}void solve(){ while (q--){  int flag,index;  scanf("%d%d",&flag,&index);  index = (index+last)%n+1;  if (flag==1){   ans = min (ans,minNum[index]);  }else{   last  = min(ans,minNum[index]);   printf("%d\n",last);  } }}int main(){ init();  build(); solve(); return 0;}



阅读全文
0 0
原创粉丝点击