首页 > 其他分享 >P8844 [传智杯 #4 初赛] 小卡与落叶

P8844 [传智杯 #4 初赛] 小卡与落叶

时间:2024-08-17 23:48:35浏览次数:11  
标签:传智杯 int siz 结点 初赛 dfn 小卡 cnt1 cnt2

原题面:P8844 [传智杯 #4 初赛] 小卡与落叶

大概题意:

给你一棵有 \(n(1\le n\le 10^5)\) 个结点的有根树,根结点标号为 \(1\),根节点的深度为 \(1\),最开始整棵树的所有结点都是绿色的。

小卡有 \(m(1\le m \le 10^5)\) 个操作。

操作一:把整棵树都染绿,之后让深度 \(\ge x\) 的结点变黄。

操作二:询问一个结点 \(x\) 的子树中有多少个黄色结点。

首先可以想到暴力做法。每次询问都暴力查询深度 \(\ge x\) 的结点的个数,时间为 \(O(n^2)\)

接下来考虑怎么优化。如何询问整个子树内的节点状态?可以想到 dfs序。在一个子树内,dfs序是连续的。一个子树 \(x\) 的 \(dfn\) 范围是 \(dfn_x\) --> \(dfn_x+siz_x-1\)

于是问题就转化成,在查询某个 \(dfn\) 范围内,所有深度大于 \(x\) 的节点数。可以想到这是一个二维偏序问题。可以将每个点的 \(dfn\) 当作横坐标,\(deep\) 当作纵坐标,将所有询问离线下来后用树状数组处理。

时间为 \(O(nlogn)\)

Code:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int f=1,x=0;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return f*x;
}
const int N=1e5+5;
int n,m;
vector<int>v[N];
int cnt,dfn[N],siz[N];
int dep[N],maxd;
void dfs(int x,int fa){
    dfn[x]=++cnt;
    siz[x]++;
    for(auto i:v[x]){
        if(i==fa)continue;
        dep[i]=dep[x]+1;
        maxd=max(maxd,dep[i]);
        dfs(i,x);
        siz[x]+=siz[i];
    }
}
int ans[N];
int cnt1,cnt2;
struct node{
    int x,y;
    int id,ff;
    bool operator<(const node& p)const{
        if(x==p.x)return y<p.y;
        else return x<p.x;
    }
}a[N],b[N];
int c[N];
inline int lowbit(int x){
    return x&-x;
}
inline void upd(int x,int w){
    for(int i=x;i<=maxd;i+=lowbit(i)){
        c[i]+=w;
    }
}
inline int qur(int x){
    int res=0;
    for(int i=x;i;i-=lowbit(i)){
        res+=c[i];
    }
    return res;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n-1;i++){
        int x=read(),y=read();
        v[x].emplace_back(y);
        v[y].emplace_back(x);
    }
    dep[1]=1;
    dfs(1,0);
    for(int i=1;i<=n;i++){
        a[i].x=dfn[i],a[i].y=dep[i];
    }
    sort(a+1,a+1+n);
    int now=maxd+1;
    for(int i=1;i<=m;i++){
        int op=read();
        if(op==1)now=read();
        else{
            int x=read();
            cnt2++;
            if(now>maxd){
                ans[cnt2]=0;
                continue;
            }
            else if(now==1){
                ans[cnt2]=siz[x];
                continue;
            }
            int xa=dfn[x],xb=dfn[x]+siz[x]-1,ya=now,yb=maxd;
            b[++cnt1]={xa-1,ya-1,cnt2,1};
            b[++cnt1]={xa-1,yb,cnt2,-1};
            b[++cnt1]={xb,ya-1,cnt2,-1};
            b[++cnt1]={xb,yb,cnt2,1};
        }
    }
    sort(b+1,b+1+cnt1);
    now=0;
    for(int i=1;i<=cnt1;i++){
        int x=b[i].x,y=b[i].y;
        while(now+1<=n&&a[now+1].x<=x){
            now++;
            upd(a[now].y,1);
        }
        ans[b[i].id]+=qur(y)*b[i].ff;
    }
    for(int i=1;i<=cnt2;i++)printf("%d\n",ans[i]);
    return 0;
}

标签:传智杯,int,siz,结点,初赛,dfn,小卡,cnt1,cnt2
From: https://www.cnblogs.com/TanHaoren/p/18365181

相关文章

  • CSP初赛知识点讲解(二)
    CSP初赛知识点讲解(二)进制转换基本定义n进制转十进制十进制转n进制n进制转m进制小数的进制转换例题训练(四)进制转换基本定义十进制:逢十进一(包含数字0~9)(365......
  • 历年CSP-J初赛真题解析 | 2013年CSP-J初赛阅读程序(23-26)
    学习C++从娃娃抓起!记录下CSP-J备考学习过程中的题目,记录每一个瞬间。附上汇总贴:历年CSP-J初赛真题解析|汇总_热爱编程的通信人的博客-CSDN博客#include<iostream>usingnamespacestd;intmain(){inta,b;cin>>a>>b;cout<<a<<"+"<<b<<......
  • NOIP 2012 提高组初赛试题
    第1题目前计算机芯片(集成电路)制造的主要原料是(),它是一种可以在沙子中提炼出的物质。 A.硅 B.铜 C.锗 D.铝本题共1.5分第2题()是主要用于显示网页服务器或者文件系统的HTML文件内容,并让用户与这些文件交互的一种软件。 A.资源管理器 B.浏览器 C.......
  • 8.1日CSP-J初赛内容总结
    8.1日CSP-J初赛内容总结补充知识点:假设结构体为Point类型structPoint{intx,y;}两种赋值方式PointA;A.x=......;A.y=......;PointA=Point{1,2};整体赋值,将{}里的按先后赋值给x,y小于号重写:优先队列之中booloperator<(const结构体......
  • 8.2日CSP-J初赛内容总结
    8.2日CSP-J初赛内容总结Adobe:PS,PR,......Reader微软:Onedrive(存文件),Excel(表格),Word(文字编辑),Onenote(笔记),PowerPoint(PPT)位号从正数部分最低位开始编号,0到更大的数字。位号从左往右的小数部分从\(-1\)开始编号,编号变小基数:进制的进位数字位权:基数的位号次幂......
  • 8.3日CSP-J初赛内容总结
    8.3日CSP-J初赛内容总结优先级\(括号>非>与>或\)\(括号>逻辑运算>位运算\)\(括号>按位取反>按位与>按位或=按位异或\)按位与或非\(\to\)补码按位取反补码所有位取反按位与将\(2\)个补码对其地位逐位比较1的个数基本上等于\(n\)除\(2\)的次数\(O(\logn)\)STL......
  • 四川省熊猫杯初赛和决赛题WP
    初赛web_ezcmsswagger泄露test/test测试账号登录,/sys/user/**没有做鉴权,可以添加一个超级管理员用户,此时仍然不知道roleId。并且role模块没有未授权。继续阅读user模块,发现接口这里存在roleid泄露,这里填入前面泄露的admin的id fcf34b56-a7a2-4719-9236-867495e74c31GET /sys/use......
  • 信奥生(OIER)请看,包囊初赛复赛的全真模拟赛!
    luogu动态追踪!唠唠嗑感谢tyw代理团主对比赛的贡献,但是由于我和tyw的关系紧张,tyw取消了我和她的一切合作。CTFPC-3rd的出题、宣传工作都交到了我手上,我这次亚历山大。CTFPC-3RD举办时间:中秋节前后,更具体时间待开学后进一步通知。tyw首次提出了出初赛题的想法,我也完成......
  • CSP 初赛复习 :计算机系统原理
            计算机系统是一个复杂的电子机器,‌它能够按照程序运行,‌自动、‌高速处理海量数据。‌这个系统主要由硬件系统和软件系统组成。‌硬件系统包括各种物理组件,‌如处理器、‌内存、‌存储设备等,‌而软件系统则包括操作系统、‌应用程序和其他必要的软件。‌硬件......
  • 2024年第三届钉钉杯大学生大数据挑战赛初赛题目初赛B:医疗门诊患者及用药数据案例分析
    (着重更新B题,A题只更新一部分)持续更新中。。2024年第三届钉钉杯大学生大数据挑战赛初赛题目初赛B:医疗门诊患者及用药数据案例分析一、问题背景:智慧医疗的出现,主要是因为传统医疗存在管理系统的不完善、医疗成本高、渠道少、覆盖面低等问题,因此需要建立......