Advertisement
a53

infestation

a53
Dec 7th, 2019
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.84 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. using namespace std;
  5. int n,q;
  6. vector<int> Graph[300111];
  7. int sz[300111];
  8. int parent[300111];
  9. int inId[300111];
  10. int inEnd[300111];
  11. int inCounter = 0;
  12.  
  13. void DFS(int ver)
  14. {
  15. int i;
  16.  
  17. inCounter++;
  18. inId[ver] = inCounter;
  19.  
  20. sz[ver] = 1;
  21.  
  22. for (i=0;i<Graph[ver].size();i++)
  23. {
  24. DFS(Graph[ver][i]);
  25. sz[ver] += sz[ Graph[ver][i] ];
  26. }
  27.  
  28. inEnd[ver] = inCounter;
  29. }
  30.  
  31. int hCounter = 1;
  32. int heavyChild[300111];
  33. vector<int> heavyPaths[300111];
  34. int myPath[300111];
  35. int hpInd[300111];
  36. vector<int> HIT[300111];
  37. int HLEAFOFFSET[300111];
  38.  
  39. void buildHL(int ver, int hid)
  40. {
  41. int i;
  42.  
  43. heavyPaths[hid].push_back(ver);
  44. myPath[ver] = hid;
  45. hpInd[ver] = heavyPaths[hid].size();
  46.  
  47. for (i=0;i<Graph[ver].size();i++)
  48. {
  49. if (sz[ Graph[ver][i] ] > sz[ver] / 2)
  50. {
  51. heavyChild[ver] = Graph[ver][i];
  52. buildHL(Graph[ver][i], hid);
  53. }
  54. else
  55. {
  56. hCounter++;
  57. buildHL(Graph[ver][i], hCounter);
  58. }
  59. }
  60. }
  61.  
  62. struct status
  63. {
  64. int infChildren;
  65. int infVer;
  66.  
  67. status(): infChildren(0), infVer(0) {}
  68. status(int a, int b): infChildren(a), infVer(b) {}
  69.  
  70. status operator+(const status &other) const
  71. {
  72. return status(infChildren + other.infChildren, infVer + other.infVer);
  73. }
  74. };
  75.  
  76. int explodeTimestamp[300111];
  77. int clearTimestamp[300111];
  78. status IT[1200111];
  79. int LEAFOFFSET;
  80.  
  81. void hpSet(int ver,int val)
  82. {
  83. int hp = myPath[ver];
  84. int ind = hpInd[ver];
  85.  
  86. ind += HLEAFOFFSET[hp];
  87. HIT[hp][ind] = val;
  88. ind /= 2;
  89.  
  90. while(ind > 0)
  91. {
  92. HIT[hp][ind] = HIT[hp][2*ind] + HIT[hp][2*ind+1];
  93. ind /= 2;
  94. }
  95. }
  96.  
  97. int hpVal(int ver)
  98. {
  99. int hp = myPath[ver];
  100. int ind = hpInd[ver];
  101.  
  102. return HIT[hp][ind+HLEAFOFFSET[hp]];
  103. }
  104.  
  105. int recNext(int hp, int ver, int L, int R, int ind)
  106. {
  107. if (L > ind || HIT[hp][ver] == 0)
  108. return 0;
  109.  
  110. if (L == R)
  111. return L;
  112.  
  113. int ret = recNext(hp, 2*ver+1, (L+R)/2+1, R, ind);
  114.  
  115. if (ret != 0)
  116. return ret;
  117. else
  118. return recNext(hp, 2*ver, L, (L+R)/2, ind);
  119. }
  120.  
  121. int getNext(int ver)
  122. {
  123. int hp = myPath[ver];
  124. if (HIT[hp][1] == 0)
  125. return 0;
  126.  
  127. int ind = hpInd[ver];
  128.  
  129. int nextInd = recNext(hp, 1, 1, HLEAFOFFSET[hp] + 1, ind - 1);
  130.  
  131. if (nextInd == 0)
  132. return 0;
  133.  
  134. return heavyPaths[hp][nextInd-1];
  135. }
  136.  
  137. void sumSetInfest(int ver,int infVal)
  138. {
  139. int ind = inId[ver];
  140.  
  141. ind += LEAFOFFSET;
  142. IT[ind].infVer = infVal;
  143. ind /= 2;
  144.  
  145. while(ind > 0)
  146. {
  147. IT[ind] = IT[2*ind] + IT[2*ind+1];
  148. ind /= 2;
  149. }
  150. }
  151.  
  152. bool pathRootIsInfested(int ver)
  153. {
  154. int ind = inId[ver];
  155. return clearTimestamp[ind] < explodeTimestamp[ inId[parent[ver]] ];
  156. }
  157.  
  158. bool isHeavyRoot(int ver)
  159. {
  160. return (heavyPaths[ myPath[ver] ][0] == ver && ver != 1);
  161. }
  162.  
  163. bool isInfested(int ver)
  164. {
  165. if (isHeavyRoot(ver))
  166. return pathRootIsInfested(ver);
  167. else
  168. return IT[inId[ver] + LEAFOFFSET].infVer == 1;
  169. }
  170.  
  171. void hpRootChangeInfest(int ver, int val)
  172. {
  173. int ind = inId[parent[ver]];
  174.  
  175. ind += LEAFOFFSET;
  176. IT[ind].infChildren += val;
  177. ind /= 2;
  178.  
  179. while(ind > 0)
  180. {
  181. IT[ind] = IT[2*ind] + IT[2*ind+1];
  182. ind /= 2;
  183. }
  184.  
  185. return;
  186. }
  187.  
  188. void hpRootClearChildren(int ver)
  189. {
  190. int ind = inId[ver];
  191. ind += LEAFOFFSET;
  192. IT[ind].infChildren = 0;
  193. ind /= 2;
  194.  
  195. while(ind > 0)
  196. {
  197. IT[ind] = IT[2*ind] + IT[2*ind+1];
  198. ind /= 2;
  199. }
  200. }
  201.  
  202. status sumRec(int ver,int L,int R,int l,int r)
  203. {
  204. if (L > r || R < l)
  205. return status(0, 0);
  206. else if (L >= l && R <= r)
  207. return IT[ver];
  208. else
  209. return sumRec(2*ver, L, (L+R)/2, l, r) + sumRec(2*ver+1, (L+R)/2+1, R, l, r);
  210. }
  211.  
  212. void explode(int ver, int immune, int ts)
  213. {
  214. int cnt;
  215.  
  216. explodeTimestamp[inId[ver]] = ts;
  217. clearTimestamp[inId[immune]] = ts + 1;
  218.  
  219. cnt = Graph[ver].size();
  220. if (immune != 0)
  221. cnt--;
  222. if (heavyChild[ver] != 0 && heavyChild[ver] != immune)
  223. {
  224. cnt--;
  225. hpSet(heavyChild[ver], 1);
  226. sumSetInfest(heavyChild[ver], 1);
  227. }
  228.  
  229. if (isHeavyRoot(ver) && isInfested(ver))
  230. {
  231. hpRootChangeInfest(ver, -1);
  232. }
  233. clearTimestamp[inId[ver]] = ts;
  234.  
  235. int ind = inId[ver];
  236.  
  237. ind += LEAFOFFSET;
  238. IT[ind] = status(cnt, 0);
  239. ind /= 2;
  240.  
  241. while(ind > 0)
  242. {
  243. IT[ind] = IT[2*ind] + IT[2*ind+1];
  244. ind /= 2;
  245. }
  246.  
  247. ///cout<<"Finished exploding "<<ver<<endl;
  248. ///cout<<isInfested(2)<<endl;
  249. ///cout<<explodeTimestamp[inId[ver]]<<" this explodes"<<endl;
  250. ///cout<<clearTimestamp[inId[2]]<<" two is cleared"<<endl;
  251. }
  252.  
  253. void infest(int x)
  254. {
  255. hpSet(x, 1);
  256. ///cout<<x<<" infested"<<endl;
  257. if (isHeavyRoot(x))
  258. {
  259. if (!pathRootIsInfested(x))
  260. {
  261. ///cout<<"new heavy root inf"<<endl;
  262. hpRootChangeInfest(x, 1);
  263. ///cout<<IT[inId[x]+LEAFOFFSET].infChildren<<";"<<IT[inId[x]+LEAFOFFSET].infVer<<endl;
  264. clearTimestamp[inId[x]] = explodeTimestamp[ inId[parent[x]] ] - 1;
  265. }
  266. }
  267. else
  268. {
  269. sumSetInfest(x, 1);
  270. }
  271. }
  272.  
  273. void killPath(int x, int ts)
  274. {
  275. ///cout<<"QUERY 2 with "<<x<<endl;
  276.  
  277. int comefrom = 0;
  278.  
  279. int pathSize = 0, suspicious = 0;
  280. int pathSwitch = 0;
  281. int ctr = 0;
  282.  
  283. while(x > 0)
  284. {
  285. pathSize++;
  286. ///cout<<"Considering "<<x<<endl;
  287.  
  288. if (hpVal(x) == 1 || isHeavyRoot(x))
  289. {
  290. suspicious++;
  291. ///cout<<"Potentially infested"<<endl;
  292.  
  293. if (hpVal(x) == 1)
  294. hpSet(x, 0);
  295.  
  296. if (isInfested(x))
  297. {
  298. ///cout<<"Actually infested"<<endl;
  299. explode(x, comefrom, ts);
  300. }
  301. }
  302.  
  303. int hpRoot = heavyPaths[ myPath[x] ][0];
  304.  
  305. if (hpRoot == x)
  306. {
  307. comefrom = x;
  308. x = parent[x];
  309. }
  310. else
  311. {
  312. int suspect = getNext(x);
  313.  
  314. if (suspect == 0 || hpInd[suspect] > hpInd[x])
  315. suspect = hpRoot;
  316.  
  317. comefrom = heavyChild[suspect];
  318. x = suspect;
  319. }
  320. }
  321. }
  322.  
  323. void clearSubtree(int x, int ts)
  324. {
  325. if (isHeavyRoot(x) && isInfested(x))
  326. {
  327. hpRootChangeInfest(x, -1);
  328. }
  329. else
  330. {
  331. sumSetInfest(x, 0);
  332. }
  333. hpSet(x, 0);
  334. clearTimestamp[ inId[x] ] = ts;
  335.  
  336. if (heavyChild[x] != 0)
  337. {
  338. hpSet(heavyChild[x], 0);
  339. sumSetInfest(heavyChild[x], 0);
  340. }
  341.  
  342. hpRootClearChildren(x);
  343. explodeTimestamp[inId[x]] = -ts;
  344. }
  345.  
  346. int sumSubtree(int x)
  347. {
  348. status sum = sumRec(1, 1, LEAFOFFSET+1, inId[x], inEnd[x]);
  349. int ans = sum.infChildren + sum.infVer;
  350.  
  351. if (isHeavyRoot(x) && isInfested(x))
  352. {
  353. ans++;
  354. }
  355.  
  356. return ans;
  357. }
  358.  
  359. int main()
  360. {
  361. int i,j;
  362.  
  363. scanf("%d",&n);
  364.  
  365. LEAFOFFSET = 1;
  366. while(LEAFOFFSET < n)
  367. LEAFOFFSET *= 2;
  368. LEAFOFFSET--;
  369.  
  370. for (i=2;i<=n;i++)
  371. {
  372. scanf("%d",&parent[i]);
  373.  
  374. Graph[parent[i]].push_back(i);
  375. }
  376.  
  377. DFS(1);
  378. buildHL(1, 1);
  379.  
  380. for (i=1;i<=hCounter;i++)
  381. {
  382. HLEAFOFFSET[i] = 1;
  383. while(HLEAFOFFSET[i] < heavyPaths[i].size())
  384. HLEAFOFFSET[i] *= 2;
  385. HLEAFOFFSET[i]--;
  386.  
  387. HIT[i].resize(2*HLEAFOFFSET[i] + 2, 0);
  388. }
  389.  
  390. scanf("%d",&q);
  391.  
  392. for (i=1;i<=q;i++)
  393. {
  394. int cm, x;
  395.  
  396. scanf("%d %d",&cm,&x);
  397.  
  398. if (cm == 1)
  399. infest(x);
  400. else if (cm == 2)
  401. killPath(x, 2*i);
  402. else if (cm == 3)
  403. clearSubtree(x, 2*i);
  404. else
  405. printf("%d\n",sumSubtree(x));
  406. }
  407. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement