BZOJ 3653 谈笑风生

ORZ blutrex。。。。。。

主席树。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 1000500
#define maxq 1000500
#define maxe 1600500
using namespace std;
struct edge
{
    long long v,nxt;
}e[maxe];
struct answer
{
    long long sum1,sum2;
};
long long n,q,x,y,nume=0,g[maxv],size[maxv],dis[maxv],w[maxv],mx[maxv],mxdis=0,cnt=0,fw[maxv];
long long root[maxv],ls[maxv<<3],rs[maxv<<3],val1[maxv<<3],val2[maxv<<3],tot=0;
void addedge(long long u,long long v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void dfs(long long x,long long fath)
{
    size[x]=1;w[x]=++cnt;mx[x]=w[x];fw[cnt]=x;
    for (long long i=g[x];i;i=e[i].nxt)
    {
        long long v=e[i].v;
        if (v!=fath)
        {
            dis[v]=dis[x]+1;mxdis=max(mxdis,dis[v]);
            dfs(v,x);
            size[x]+=size[v];
            mx[x]=max(mx[x],mx[v]);
        }
    }
}
void build(long long &now,long long left,long long right)
{
    now=++tot;val1[now]=val2[now]=0;
    if (left==right) return;
    long long mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
}
void modify(long long last,long long &now,long long left,long long right,long long pos,long long x)
{
    now=++tot;ls[now]=ls[last];rs[now]=rs[last];
    val1[now]=val1[last]+x;val2[now]=val2[last]+1;
    if (left==right) return;
    long long mid=(left+right)>>1;
    if (pos<=mid) modify(ls[last],ls[now],left,mid,pos,x);
    else modify(rs[last],rs[now],mid+1,right,pos,x);
}
answer merge(answer x,answer y)
{
    answer ret;
    ret.sum1=x.sum1+y.sum1;
    ret.sum2=x.sum2+y.sum2;
    return ret;
}
answer ask(long long last,long long now,long long left,long long right,long long l,long long r)
{
    answer ret;
    if ((left==l) && (right==r))
    {
        ret.sum1=val1[now]-val1[last];
        ret.sum2=val2[now]-val2[last];
        return ret;
    }
    long long mid=(left+right)>>1;
    if (r<=mid) return ask(ls[last],ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask(rs[last],rs[now],mid+1,right,l,r);
    else return merge(ask(ls[last],ls[now],left,mid,l,mid),ask(rs[last],rs[now],mid+1,right,mid+1,r));
}
int main()
{
    scanf("%lld%lld",&n,&q);
    for (long long i=1;i<=n-1;i++)
    {
        scanf("%lld%lld",&x,&y);
        addedge(x,y);
        addedge(y,x);
    }
    dfs(1,1);
    build(root[0],0,mxdis);
    for (long long i=1;i<=n;i++)
        modify(root[i-1],root[i],0,mxdis,dis[fw[i]],size[fw[i]]);
    for (long long i=1;i<=q;i++)
    {
        scanf("%lld%lld",&x,&y);
        long long ret=min(dis[x],y)*(size[x]-1);
        answer regis=ask(root[w[x]-1],root[mx[x]],0,mxdis,min(dis[x]+1,mxdis),min(dis[x]+y,mxdis));
        ret+=regis.sum1-regis.sum2;
        printf("%lld\n",ret);
    }
    return 0;
}
时间: 2024-12-30 01:47:14

BZOJ 3653 谈笑风生的相关文章

bzoj 3653 谈笑风生——主席树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653 原来一直想怎么线段树合并.可是不会把角标挪一位. 查询的其实是子树内一段深度的点的 siz 和.因为是子树内,所以按 dfs 序建立主席树,角标是 dep ,值是 siz . 注意 long long .而且数组 *19 就会 RE ,*20就好了.不知为何. #include<iostream> #include<cstdio> #include<cstring

3653: 谈笑风生

3653: 谈笑风生 链接 分析: $ans = min(deep[x] - 1, k) * siz[x] - 1 +\sum\limits_{y是u子树内的点}(siz[y] - 1)$ 前面的可以$O(1)$算,后面的那一部分可以dfs序+主席树维护. 或者dfs的过程中+线段树合并.或者长链剖分. 代码: #include<cstdio> #include<algorithm> #include<cstring> #include<iostream>

bzoj 3653

每个点维护一颗以深度为下标,size-1为值的线段树,保存整颗子树的信息,这样就可以查询了,但是如果为每个节点都建立这么一颗树,显然会MLE,所以考虑在DFS序上建立主席树,然后每个节点原来对应的线段树树就是现在的两个线段树相减所得到的树. 1 /************************************************************** 2 Problem: 3653 3 User: idy002 4 Language: C++ 5 Result: Accept

【BZOJ】【3653】谈笑风生

dfs序+可持久化线段树 好吧……是我too naive 这题……$$ans=min(dep[x],k)×(size[x]-1)+\sum_{y在x的子树中,且dis(x,y)<=k}(size[y]-1)$$ 那么重点是后面sigma的部分,这里看到子树中信息的统计可以用dfs序……但是对子树中dep在某个范围内的点的size求和? 我们可以用权值线段树呀-dep做关键字,size的和是线段树上统计的额外信息,那么对整个dfs序做可持久化线段树就可以了……查询的时候就像普通线段树一样. 调了很

【BZOJ-3653】谈笑风生 DFS序 + 可持久化线段树

3653: 谈笑风生 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 628  Solved: 245[Submit][Status][Discuss] Description 设T 为一棵有根树,我们做如下的定义:• 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道高明到哪里去了”.• 设a 和 b 为 T 中的两个不同节点.如果 a 与 b 在树上的距离不超过某个给定常数x,那么称“a 与b 谈笑风生”.给定一棵n个节点的

【20151105noip膜你赛】bzoj3652 bzoj3653

题目仿佛在讽刺我... 第一题: 题解: 考虑枚举区间右端点,维护所以左到当前的 and 和 or .注意 and 每次变化至少有一个二进制位从1变 0,or 每次至少有一个位从0变 1,所以最多有log段不同的值.用两个链表维护这log个值,暴力计算答案即可.O( nlogn) 我原本打的是一个树状数组的O(nlognlogn)算法..然后被卡了..只有50分.. 看了看奥爷爷的代码,发现他直接用一个链表同时维护and和or值,真奇怪啊不是(logn)^2吗..然后男神说这个也是log级别的,

lct 模版题 bzoj 2002 2049

很早就有人给我推荐的模版题,然后我最近才刷的(' '    ) 昨天的tree 不知道比他们高到哪里去了,我和他谈笑风生啊! bzoj 2002 弹飞绵羊 重点:这道题的cut和link 由于这道题链的特殊性所以不能用提根的方法搞,可以注意到每一次cut位置一定是前面的一个元素,所以access 上去之后直接把左边的儿子丢掉就行了(我原来的cut 是在不知道两个点的儿子关系时就强行提根(' '    )) 然后link的时候直接把cut的那一棵splay接过去就行了 1 #include <io

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445