首页 > 其他分享 >数星星

数星星

时间:2024-03-23 18:33:39浏览次数:15  
标签:遍历 int 数星星 while 区间 getchar

题目链接

戳这

\(Solution\)

对于一个树他的子树的\(dfs\)序一定是连续的,所以可以把这个树化成链,问题就转化为了对于一段区间中星星的种类是否都不同,然后这个东西可以继续变成区间的不同种类个数是否等于区间长度,区间不同种类个数就很好求了可以看看HH的项链 如果这题范围是\(1e5\)的话可以用莫队暴力搞过去,但是是\(2e6\)所以就只能用\(log\)的做法。
将区间按右端点排序然后遍历一下看这个位置是否出现过,如果出现过则把上个位置的值\(-1\)。遍历到一个点将这个点的值标记一下表示最后出现的位置。然后将这个点的值\(+1\).对于答案就是区间的和。这个东西用树状数组或者线段树搞一下就行。

\(code\)

```#include<bits/stdc++.h>
using namespace std;
int read() {
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
int val[2000011];
struct tree {
    int next,to;
}a[4000011];
struct node{
    int l,r,id;
}c[2000011];
int cnt,head[2000011],siz[2000011],dfn[2000011],b[2000011],js;
void add(int x,int y){
    a[++cnt].next=head[x];
    a[cnt].to=y;
    head[x]=cnt;
}
void dfs(int x){
    siz[x]=1;
    dfn[x]=++js;
    b[js]=val[x];
    for(int i=head[x];i;i=a[i].next){
            int v=a[i].to;
            dfs(v);
            siz[x]+=siz[v];
    }
}
int d[2000011],n,x;
bool cmp(const node & a , const node & b ){
    return a.r<b.r;
}
int lowbit(int x){
    return x&(-x);
}
void Add(int x,int c){
    while(x<=n) d[x]+=c,x+=lowbit(x);
}
int sum(int x){
    int ans=0;
    while(x) ans+=d[x],x-=lowbit(x);
    return ans;
}
int bj[2000011];
int main(){
    n=read(),x;
    for(int i=1;i<=n;i++) val[i]=read();
    for(int i=1;i<n;i++) x=read(),add(x,i+1);
    dfs(1);
    for(int i=1;i<=n;i++){
        c[i].l=dfn[i],c[i].r=dfn[i]+siz[i]-1,c[i].id=i;
    }
    sort(c+1,c+1+n,cmp);
    int now=1,ans=0;
    for(int i=1;i<=n;i++){
        for(int j=now;j<=c[i].r;j++){
            if(bj[b[j]]) Add(bj[b[j]],-1);
            Add(j,1);
            bj[b[j]]=j;
        }
        now=c[i].r+1;
        if(sum(c[i].r)-sum(c[i].l-1)==siz[c[i].id]) ans++;
    }
    cout<<ans;
}

标签:遍历,int,数星星,while,区间,getchar
From: https://www.cnblogs.com/hbxblog/p/18091524

相关文章

  • 数星星题解补充
    题解中那个看似暴力的染色,实际上正确性显然,直接看75%的时间复杂度证明然后还是直接看75分的部分它的里面说是用set维护块的前驱后继,然后全网没有一篇这样的题解,似乎全世界就我一个用这个方法于是想了一中午终于想到如何维护:就是用set记录每一个块的最后一个的位置,由于是区间覆......
  • NOIP2023-div2模拟赛20 D. 数星星
    妙妙+经典题。难度:Hard。题意给定一棵\(n\)个结点的树,点有点权。树上有一些简单路径,编号分别为\(1,2,\cdots,m\)。有\(q\)次询问,每次询问查询编号在\([l,r]\)中的路径的并的点权和。题解考虑一个经典题:定一个数列,每次询问一个区间不同元素的和。这个问题是简单的,你......
  • NC50428 数星星 Stars
    题目链接题目题目描述天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。如果一个星星的左下方(包含正左和正下)有k颗星星,就说这颗星星是k级的。例如,上图中星星5是3级的(1,2,4在它左下),星星2,4是1级的。例图中有1个0级,2个1级,1个2级,1个3级的星星。给定星星的位置,输出各级......
  • #10114. 「一本通 4.1 例 2」数星星 Stars
    给定n个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,(输入按照y值递增给出)统计每个等级有多少个点 输入按照y值递增给出,y坐标是没有用的(脑补直接求前缀......