https://codeforces.com/gym/102861/problem/E
听课也更不上,比赛过了一车人的题也不会,没了啊
这题很显然我们可以看出,由于最后一定是一个连通块属于同一个组,那么由组长o我们可以倍增到最上面的领导o1,使得最上面恰好逼近r
那么最显然的想法就是从这个根节点o1开始,他子树中所有>=l的都会+1,那么子树问题显然可以用dfs序来维护,按dfs序标号,然后分块对每块内部排序,然后左右边界的块暴力找,中间的块一定在子树中,就直接二分后用差分数组作区间加法
O(nsqrt(n)logn)快乐TLE
然后就要从另一个角度考虑统计答案了,我们把每一个小组信息挂在根节点o1上,dfs的时候就把从根节点到当前节点所有小组信息加载进权值树状数组里,然后看这些小组信息有多少是当前节点u满足的,就是这个点的答案
上面是分块代码,下面是有点卡常的代码。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxl=2e5+10;
int n,m,sz,ind,tot;
int val[maxl],aval[maxl],dfn[maxl],out[maxl],ans[maxl];
int bel[maxl],ll[maxl],rr[maxl];
LL b[maxl],c[maxl];
int f[21][maxl];
vector<int> e[maxl];
struct node
{
int val,id,dy;
}a[maxl];
inline void dfs(int u,int fa)
{
dfn[u]=++ind;
a[ind].val=-val[u];a[ind].id=ind;a[ind].dy=u;
for(int v:e[u])
dfs(v,u);
out[u]=ind;
}
inline bool cmp(const node &x,const node &y)
{
return x.val<y.val;
}
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&val[i],&f[0][i]);
if(i!=1)
e[f[0][i]].push_back(i);
}
f[0][1]=0;
for(int k=1;k<=20;k++)
for(int i=1;i<=n;i++)
f[k][i]=f[k-1][f[k-1][i]];
dfs(1,0);
sz=sqrt(n);
for(int i=1;i<=n;i++)
{
bel[i]=(i-1)/sz+1;
if(!ll[bel[i]])
ll[bel[i]]=i;
rr[bel[i]]=i;
}
for(int i=1;i<=bel[n];i++)
sort(a+ll[i],a+rr[i]+1,cmp);
for(int i=1;i<=n;i++)
aval[i]=a[i].val;
}
inline void mainwork()
{
for(int cas=1;cas<=m;cas++)
{
int o,l,r;
scanf("%d%d%d",&o,&l,&r);
for(int k=20;k>=0;k--)
if(f[k][o]!=0 && val[f[k][o]]<=r)
o=f[k][o];
int lb=(dfn[o]-1)/sz+1,rb=(out[o]-1)/sz+1;
for(int i=lb+1;i<=rb-1;i++)
if(a[ll[i]].val<=-l)
{
int rd=upper_bound(aval+ll[i],aval+rr[i]+1,-l)-aval;
c[ll[i]]++;c[rd]--;
}
for(int j=ll[lb];j<=rr[lb];j++)
if(a[j].id>=dfn[o] && a[j].id<=out[o] && a[j].val<=-l)
ans[a[j].dy]++;
if(lb==rb)
continue;
for(int j=ll[rb];j<=rr[rb];j++)
if(a[j].id>=dfn[o] && a[j].id<=out[o] && a[j].val<=-l)
ans[a[j].dy]++;
}
for(int i=1;i<=n;i++)
c[i]+=c[i-1],ans[a[i].dy]+=c[i];
}
inline void print()
{
for(int i=1;i<=n;i++)
printf("%d%c",ans[i]," \n"[i==n]);
}
int main()
{
prework();
mainwork();
print();
return 0;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxl=3e5+10;
int n,m,sz,ind,tot;
int val[maxl],ans[maxl];
int f[21][maxl];
int b[maxl],num[maxl];
vector<int> e[maxl],g[maxl];
struct que
{
int o,l,r;
}q[maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&val[i],&f[0][i]);
num[++tot]=val[i];
if(i!=1)
e[f[0][i]].push_back(i);
}
f[0][1]=0;
for(int k=1;k<=20;k++)
for(int i=1;i<=n;i++)
f[k][i]=f[k-1][f[k-1][i]];
}
inline int id(int x)
{
return lower_bound(num+1,num+1+tot,x)-num;
}
inline void add(int i,int x)
{
while(i && i<=tot)
b[i]+=x,i+=i&-i;
}
inline int sum(int i)
{
int ret=0;
while(i)
ret+=b[i],i-=i&-i;
return ret;
}
inline void dfs(int u,int fa)
{
for(int l:g[u])
add(l,1);
ans[u]=sum(val[u]);
for(int v:e[u])
dfs(v,u);
for(int l:g[u])
add(l,-1);
}
inline void mainwork()
{
for(int i=1;i<=m;i++)
{
int o,l,r;
scanf("%d%d%d",&o,&l,&r);
q[i]=que{o,l,r};
num[++tot]=l;num[++tot]=r;
}
sort(num+1,num+1+tot);
tot=unique(num+1,num+1+tot)-num-1;
for(int i=1;i<=n;i++)
val[i]=id(val[i]);
for(int i=1;i<=m;i++)
{
q[i].l=id(q[i].l);
q[i].r=id(q[i].r);
int o=q[i].o,l=q[i].l,r=q[i].r;
for(int k=20;k>=0;k--)
if(f[k][o]!=0 && val[f[k][o]]<=r)
o=f[k][o];
g[o].push_back(l);
}
dfs(1,0);
}
inline void print()
{
for(int i=1;i<=n;i++)
printf("%d%c",ans[i]," \n"[i==n]);
}
int main()
{
prework();
mainwork();
print();
return 0;
}