• Codefores 932D Tree


    原题传送门

    一道题意很复杂的题目,为了表达一句话的意思,用了四句话去描述,纯粹为了误导

    大致题意:一棵树,每个结点i会有一个权值weighti,初始时只有一个权值为0的根节点1。给定Q(Q≤4*105)个操作,操作分两类:

    1.1 p q,表示新建结点cnt+1,权值为q,该结点与p结点连边。

    2.2 p q,表示求最长的序列P,满足P1=p,对i>1,都有:Pi是Pi-1与根结点路径上离Pi-1最近的权值不小于weighti的点,且所有weightPi加起来(有点拗口,看不懂的可以看原题描述)

    具体有一些区别:其实就是强制在线辣,请以实际描述为准。

    分析:很明显能看出一些不变的东西:结点只增不减,而后续结点的加入不会影响之前结点的性质,也就是说,一个结点的信息在他加入的时候就已经完全确定,而这些信息都能由祖先的信息推出,于是想到倍增。具体维护两个信息st_par和st_sum(我代码里省事把st_par简写为st,st_sum简写为sum),其中st_par[i][j]表示从结点i向上“跳”2j步的结点编号,这里“跳”一步指的是进行一次寻找“到根结点路径上第一个不小于当前结点权值的结点”的操作,st_sum[i][j]表示跳的过程中所有经过结点(不包括起点)的权值之和。能这样维护的原因是:操作2中的序列其实是唯一的,我只要能快速维护找到下一个结点的操作就行。这样倍增的轮廓就出来了,但是还有一件事要解决:第一步也就是st[i][0]怎么计算?这里就要用到二分的思想了:设tmp为i的父亲,利用二分锁定离i最近的符合要求的点,具体怎么实现就不用多说了,我想说的是我原本的写法:我原来写的是由i的父亲一步一步按st[tmp][0]的方式往上跳,实测两种写法没有任何时间上的差别,但是复杂度肯定是不一样的。。

    代码随便看看。。

      1 /*    Codeforces 932D Tree
      2     1st Edition:2018.2.15 Thursday
      3     2nd Edition:2018.2.16 Friday
      4     Algorithm:倍增
      5 */
      6 #include <iostream>
      7 #include <cstdio>
      8 #include <algorithm>
      9 #include <cmath>
     10 #include <cstring>
     11 #include <vector>
     12 #include <map>
     13 #include <set>
     14 #include <bitset>
     15 #include <queue>
     16 #include <deque>
     17 #include <stack>
     18 #include <iomanip>
     19 #include <cstdlib>
     20 #include <ctime>
     21 #include <cctype>
     22 using namespace std;
     23 
     24 #define is_lower(c) (c>='a' && c<='z')
     25 #define is_upper(c) (c>='A' && c<='Z')
     26 #define is_alpha(c) (is_lower(c) || is_upper(c))
     27 #define is_digit(c) (c>='0' && c<='9')
     28 #define stop system("PAUSE")
     29 #define ForG(a,b,c) for(rg int (a)=c.head[b];(a);(a)=c.E[a].nxt)
     30 #define For(a,b,c) for(rg int (a)=(b);(a)<=(c);++a)
     31 #define min(a,b) ((a)<(b)?(a):(b))
     32 #define max(a,b) ((a)>(b)?(a):(b))
     33 #define shl(x,y) ((x)<<(y))
     34 #define shr(x,y) ((x)>>(y))
     35 #define mp make_pair
     36 #define pb push_back
     37 #define rg register
     38 #ifdef ONLINE_JUDGE
     39 #define hash rename_hash
     40 #define next rename_next
     41 #define prev rename_prev
     42 #endif
     43 typedef long long ll;
     44 typedef unsigned long long ull;
     45 typedef pair<int,int> pii;
     46 typedef pair<ll,ll> pll;
     47 typedef vector<int> vi;
     48 typedef double db;
     49 const ll inf=1000000007LL;
     50 const db EPS=1e-14;
     51 const ll inf_ll=(ll)1e18;
     52 const ll maxn=400005LL;
     53 const ll mod=1000000007LL;
     54 
     55 int n,cnt;
     56 ll last;
     57 ll weight[maxn],sum[maxn][20];
     58 int par[maxn],st[maxn][20];
     59 
     60 int main(){
     61     scanf("%d",&n);
     62     cnt=1;
     63     while(n--){
     64         ll opt,p,q;
     65         scanf("%I64d %I64d %I64d",&opt,&p,&q);
     66         p^=last;q^=last;
     67         if(opt^2){
     68             par[++cnt]=p;
     69             weight[cnt]=q;
     70             int tmp=p;
     71             if(weight[tmp]<q){
     72                 for(int i=19;i+1;--i) if(st[tmp][i] && weight[st[tmp][i]]<q){
     73                     tmp=st[tmp][i];
     74                 }
     75                 tmp=st[tmp][0];
     76             }
     77             st[cnt][0]=tmp;
     78             sum[cnt][0]=weight[tmp];
     79             For(i,1,19) if(st[cnt][i-1] && st[st[cnt][i-1]][i-1]){
     80                 st[cnt][i]=st[st[cnt][i-1]][i-1];
     81                 sum[cnt][i]=sum[cnt][i-1]+sum[st[cnt][i-1]][i-1];
     82             }
     83         }else{
     84             ll nowsum=weight[p];
     85             if(nowsum>q){
     86                 puts("0");
     87                 last=0;
     88                 continue;
     89             }
     90             int now=p,res=1;
     91             for(int i=19;i>=0;--i) if(st[now][i] && sum[now][i]+nowsum<=q){
     92                 nowsum+=sum[now][i];
     93                 now=st[now][i];
     94                 res+=shl(1,i);
     95             }
     96             printf("%d
    ",res);
     97             last=(ll)res;
     98         }
     99     }
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    Android Studio 快捷键、Debug的使用
    android 控件获取 获取焦点
    jquery里面获取div区块的宽度与高度
    C# ASP.NET MVC 配置允许跨域访问
    分页跳转计算公式
    在vue-cli3 中import引入一个没有export default{}的js文件
    vue中引入css文件
    Vue 导入文件import、路径@和.的区别
    npm 如何查看一个包的版本信息?
    Chrome浏览器常用键盘快捷键介绍
  • 原文地址:https://www.cnblogs.com/xuzihanllaa/p/8450352.html
Copyright © 2020-2023  润新知