Codeforces 932D - Tree

932D - Tree

思路:

树上倍增

anc[i][u]:u的2^i祖先

mx[i][u]:u到它的2^i祖先之间的最大值,不包括u

pre[i][u]:以u开始的递增序列的2^i祖先

sum[i][u]:以u开始递增序列从u到2^i祖先的和,不包括u

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))

const int N=4e5+5;
const ll INF=1e15;
int anc[20][N],pre[20][N];
ll sum[20][N],w[N],mx[20][N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int q,cnt=1,op;
    ll l,r,last=0;
    w[0]=INF;
    for(int i=0;i<20;i++)sum[i][1]=sum[i][0]=mx[i][1]=mx[i][0]=INF;
    cin>>q;
    while(q--){
        cin>>op>>l>>r;
        l^=last;
        r^=last;
        if(op==1){
            anc[0][++cnt]=l;
            w[cnt]=r;
            mx[0][cnt]=w[l];
            for(int i=1;i<20;i++){
                anc[i][cnt]=anc[i-1][anc[i-1][cnt]];
                mx[i][cnt]=max(mx[i-1][cnt],mx[i-1][anc[i-1][cnt]]);
            }
            int t=cnt;
            for(int i=19;i>=0;i--){
                if(mx[i][t]<w[cnt]){
                    t=anc[i][t];
                }
            }
            pre[0][cnt]=anc[0][t];
            sum[0][cnt]=w[anc[0][t]];
            for(int i=1;i<20;i++){
                pre[i][cnt]=pre[i-1][pre[i-1][cnt]];
                sum[i][cnt]=sum[i-1][cnt]+sum[i-1][pre[i-1][cnt]];
            }
        }
        else{
            int ans=0;
            if(w[l]<=r){
                ans=1;
                r-=w[l];
                for(int i=19;i>=0;i--){
                    if(sum[i][l]<=r){
                        r-=sum[i][l];
                        l=pre[i][l];
                        ans+=1<<i;
                    }
                }
            }
            last=ans;
            cout<<ans<<endl;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/widsom/p/8496110.html

时间: 2024-10-16 10:10:01

Codeforces 932D - Tree的相关文章

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加起来(有点拗口,看不懂的可以看原题描述

Codeforces 570D TREE REQUESTS dfs序+树状数组 异或

http://codeforces.com/problemset/problem/570/D Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of?n?vertices. Each vertex contains a lowercase

Codeforces 570D Tree Requests(Dsu On the Tree)

题目链接 Tree Requests 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 7 typedef long long LL; 8 9 const int N = 500010; 10 const int A = 31; 11 12 int cntf[N], sz[N], h[N]; 13 vector <i

Codeforces 23E Tree(树型DP)

题目链接 Tree dp[x][i]表示以x为根的子树中x所属的连通快大小为i的时候 答案最大值 用dp[x][j] * dp[y][k] 来更新dp[x][j + k]. (听高手说这类题的套路其实都差不多) 因为这题输出数据会很大所以用Java-- QAQ 1 import java.util.*; 2 import java.io.*; 3 import java.math.*; 4 5 public class Main{ 6 static final int maxn = 710; 7

Codeforces 570D TREE REQUESTS dfs序+树状数组

链接 题解链接:点击打开链接 题意: 给定n个点的树,m个询问 下面n-1个数给出每个点的父节点,1是root 每个点有一个字母 下面n个小写字母给出每个点的字母. 下面m行给出询问: 询问形如 (u, deep) 问u点的子树中,距离根的深度为deep的所有点的字母能否在任意排列后组成回文串,能输出Yes. 思路:dfs序,给点重新标号,dfs进入u点的时间戳记为l[u], 离开的时间戳记为r[u], 这样对于某个点u,他的子树节点对应区间都在区间 [l[u], r[u]]内. 把距离根深度相

Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

题目链接  Tree and Queries 题目大意  给出一棵树和每个节点的颜色.每次询问vj, kj 你需要回答在以vj为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少为kj. (莫队居然可以过) 首先转DFS序,这样就变成了区间查询. 然后直接套用莫队,求出每次询问状态下的t[],t[k]表示当前区间内拥有k个节点的颜色数量. 然后统计t[k] + t[k + 1], ..., t[MAX]即可,这个过程用树状数组维护. #include <bits/stdc++.h>

Codeforces 911F Tree Destruction(贪心 &amp;&amp; 树的直径)

题目链接  Tree Destructi 题意  给定一棵树,每次可以选定树上的两个叶子,并删去其中的一个.答案每次加上两个选定的叶子之间的距离. 求最后答案的最大值. 首先求出树的某一条直径,令其端点分别为L, R. 把L看成树的根,那么R一定是叶子结点. 对于那些非直径上的点,离他们最远的点肯定是L或R中的一个(可能也有其他的,但是L或R肯定已经最大了) 所以依次把这些非直径上的点删掉,删掉的时候在L和R中选择一个就行了. 最后把直径删掉即可. 时间复杂度$O(nlogn)$  (应该是可以

CodeForces 375D Tree and Queries 莫队||DFS序

Tree and Queries 题意:有一颗以1号节点为根的树,每一个节点有一个自己的颜色,求出节点v的子数上颜色出现次数>=k的颜色种类. 题解:使用莫队处理这个问题,将树转变成DFS序区间,然后就是开一个数据记录下出现次数为k次的颜色数目,查询的时候直接返回这个数组中的对应的值就行了. 注意的就是记得将节点的颜色传递给dfs序对应位置的颜色. 这个忘记了找了好久的bug. 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3

CodeForces 1118F2. Tree Cutting (Hard Version)

题目简述:给定$n \leq 3 \times 10^5$个节点的树,其中一部分节点被染色,一共有$k$种不同的颜色.求将树划分成 $k$ 个不相交的部分的方案数,使得每个部分中除了未染色的节点以外的所有节点颜色相同,答案模$998244353$(质数). 解:code Step 1. 缩点 相关题目:CodeForces 76F. Tourist 观察:为使相同颜色的节点处在同一个子树中,则包含这些节点的最小子树的所有节点必然会被划分在同一部分. 因此,在随意选择一个节点作为树的根节点后,每种