[codeforces]Codeforces Global Round 1 F. Nearest Leaf

题解:  语文题????  上面说的一段代码 告诉你的是  节点编号顺序与dfs序顺序一致  也就是你  dfs序以后编号就是[1,n]  根据这个特性  那么我们只需要维护每个叶子节点到查询v的距离即可  那么我们只需要离线所有查询 然后对子树修改即可   用线段树来维护区间加和区间最小值就行

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=5e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
const ll inf=1e16;
struct edge{int t;ll v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,ll vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}

int num[MAXN];
ll a[MAXN],sum[MAXN];
bool vis[MAXN];
void dfs(int x){
    num[x]=1;
    link(x){
	sum[j->t]=sum[x]+j->v;
	if(!vis[j->t])a[j->t]=sum[j->t];
	else a[j->t]=inf;
	dfs(j->t);
	num[x]+=num[j->t];
    }
}

ll minn[MAXN<<2],flag[MAXN<<2];
void push(int rt){
    if(flag[rt]){
	flag[rt<<1]+=flag[rt];flag[rt<<1|1]+=flag[rt];
	minn[rt<<1]+=flag[rt];minn[rt<<1|1]+=flag[rt];
	flag[rt]=0;
    }
}
void up(int rt){minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);}
void built(int rt,int l,int r){
    if(l==r){minn[rt]=a[l];return ;}
    int mid=(l+r)>>1;
    built(rt<<1,l,mid);
    built(rt<<1|1,mid+1,r);
    up(rt);
}

void update(int rt,int l,int r,int ql,int qr,ll k){
    if(ql>qr)return ;
    if(ql<=l&&r<=qr){minn[rt]+=k;flag[rt]+=k;return ;}
    int mid=(l+r)>>1;
    push(rt);
    if(ql<=mid)update(rt<<1,l,mid,ql,qr,k);
    if(qr>mid)update(rt<<1|1,mid+1,r,ql,qr,k);
    up(rt);
}

ll ans;
void query(int rt,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){ans=min(ans,minn[rt]);return ;}
    int mid=(l+r)>>1;
    push(rt);
    if(ql<=mid)query(rt<<1,l,mid,ql,qr);
    if(qr>mid)query(rt<<1|1,mid+1,r,ql,qr);
    up(rt);
}

typedef struct node{
    int l,r,id;
}node;
vector<node>vec[MAXN];
ll ans1[MAXN];
int n;
void dfs2(int x){
    for(int i=0;i<vec[x].size();i++){
	ans=inf;query(1,1,n,vec[x][i].l,vec[x][i].r);
	ans1[vec[x][i].id]=ans;
    }
    link(x){
	int t=j->t;
	update(1,1,n,t,t+num[t]-1,-(j->v));
	update(1,1,n,1,t-1,j->v);
	update(1,1,n,t+num[t],n,j->v);
	dfs2(j->t);
	update(1,1,n,t,t+num[t]-1,j->v);
	update(1,1,n,1,t-1,-(j->v));
	update(1,1,n,t+num[t],n,-(j->v));
    }
}

int main(){
    n=read();int q=read();
    int u;ll k;
    inc(i,2,n)u=read(),k=read(),add(u,i,k),vis[u]=1;
    a[1]=inf;dfs(1);
    built(1,1,n);
    int v,l,r;
    inc(i,1,q)v=read(),l=read(),r=read(),vec[v].pb((node){l,r,i});
    dfs2(1);
    inc(i,1,q)printf("%lld\n",ans1[i]);
}

  

原文地址:https://www.cnblogs.com/wang9897/p/10355833.html

时间: 2024-10-07 23:46:23

[codeforces]Codeforces Global Round 1 F. Nearest Leaf的相关文章

Codeforces Global Round 1

A. Parity 签. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int b, k, a[N]; 6 7 int main() 8 { 9 while (scanf("%d%d", &b, &k) != EOF) 10 { 11 int res = 0; 12 for (int i = 1; i <= k; ++i) scanf("%d&

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu

Educational Codeforces Round 24 F. Level Generation(三分)

题目链接:Educational Codeforces Round 24 F. Level Generation 题意: 给你n个点,让你构造ans条边,使得这ans条边中至少有一半是桥. 让你求ans的最大值. 题解: 首先我们将每一个点按顺序连起来,那么可以构成n-1个桥. 然后我们可以把其中的x个点拿出来连边,这些边都不是桥. x个点最多能连x*(x-1)条边,然后剩下的n-x个点连的边将会构成桥. 然后就可以构造一个函数关系,详见check函数,然后三分一下就行了. 1 #include

Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)

题目链接:Educational Codeforces Round 21 F. Card Game 题意: 有n个卡片,每个卡片有三个值:p,c,l; 现在让你找一个最小的L,使得满足选出来的卡片l<=L,并且所有卡片的p的和不小于k. 选择卡片时有限制,任意两张卡片的c之和不能为质数. 题解: 和hdu 1565 方格取数(2)一样,都是求最大点权独立集. 不难看出来,这题再多一个二分. 注意的是在构造二部图的时候,按照c值的奇偶性构造. 当c==1时要单独处理,因为如果有多个c==1的卡片,

Codeforces Global Round 1 (A-E题解)

Codeforces Global Round 1 题目链接:https://codeforces.com/contest/1110 A. Parity 题意: 给出{ak},b,k,判断a1*b^(k-1)+a2*b^(k-2)+...+ak*b^0的奇偶性. 题解: 暴力求模2意义下的值就好了. 代码如下: #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 2e5+5; int

Educational Codeforces Round 76 F 折半枚举

Educational Codeforces Round 76 F 折半枚举 https://codeforces.com/contest/1257/problem/F 题意: 数组a,找到一个x使得a中每一个元素异或x后"二进制中1的个数"相同. 数组长度100,数字大小2^30. 思路: 折半枚举答案X,如分为X前15位和后15位.之后我们再枚举期望的"相同个数"是多少,通过hash看看能不能满足就好了. 代码: #include <bits/stdc++

【手抖康复训练1 】Codeforces Global Round 6

[手抖康复训练1 ]Codeforces Global Round 6 总结:不想复习随意打的一场,比赛开始就是熟悉的N分钟进不去时间,2333,太久没写题的后果就是:A 题手抖过不了样例 B题秒出思路手抖过不了样例,C题秒出思路手抖过不了样例*3 D题 手抖 过的了样例 ,调了1h,赛后发现变量名写错了,改一个字符就能AC... 题目等补完题一起放上来QAQ 原文地址:https://www.cnblogs.com/ttttttttrx/p/12110199.html

Educational Codeforces Round 14 - F (codeforces 691F)

题目链接:http://codeforces.com/problemset/problem/691/F 题目大意:给定n个数,再给m个询问,每个询问给一个p,求n个数中有多少对数的乘积≥p 数据范围:2≤n≤10^6, 1≤ai≤3*10^6,1≤m≤10^6, 1≤p≤3*10^6 解题思路:比赛的时候比较naive的思路是把n中的数字排序去了重之后,对于每个p,最多枚举√p步,就能得到答案.而这个naive的思路是O(p√p)的,结果T了. 后来百思不得其解,去看了官方的解答.感觉是一种很有