题解:P3712 少女与战车
前言
纯由乃打扑克啊,会了那道题这道题就差不多了。对就是这个入重编号完了之后修改的时候用的还是原编号调试两个小时。
解题过程
观察到这题在对
会的可以直接做了,不过这是模板,所以还是讲一下做法。我们先按块长为
上述过程时间复杂度大概是
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,len,a[100005],b[100005],c[100005],t,siz1,l[405],r[405],p[100005],siz[100005],id[100005],cnt,f[100005],tag[100005];
vector<int>g[100005];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<48||ch>57){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>=48&&ch<=57){
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
inline void dfs(const int x,const int fa){
c[x]+=c[fa];
f[x]=fa;
id[x]=++cnt;
a[cnt]=c[x];
b[cnt]=c[x];
siz[x]=1;
for(int i=0;i<g[x].size();++i){
if(g[x][i]==fa)continue;
dfs(g[x][i],x);
siz[x]+=siz[g[x][i]];
}
}
inline void modify(const int x,const int y,const int k){
if(p[x]==p[y]){
for(int i=x;i<=y;++i)a[i]+=k;
for(int i=l[p[x]];i<=r[p[y]];++i)b[i]=a[i];
sort(b+l[p[x]],b+r[p[y]]+1);
}
else{
for(int i=x;i<=r[p[x]];++i)a[i]+=k;
for(int i=l[p[x]];i<=r[p[x]];++i)b[i]=a[i];
sort(b+l[p[x]],b+r[p[x]]+1);
for(int i=p[x]+1;i<=p[y]-1;++i)tag[i]+=k;
for(int i=l[p[y]];i<=y;++i)a[i]+=k;
for(int i=l[p[y]];i<=r[p[y]];++i)b[i]=a[i];
sort(b+l[p[y]],b+r[p[y]]+1);
}
}
inline int getmin(const int x,const int y){
int ans=INT_MAX;
if(p[x]==p[y])for(int i=x;i<=y;++i)ans=min(ans,a[i]+tag[p[x]]);
else{
for(int i=x;i<=r[p[x]];++i)ans=min(ans,a[i]+tag[p[x]]);
for(int i=p[x]+1;i<=p[y]-1;++i)ans=min(ans,b[l[i]]+tag[i]);
for(int i=l[p[y]];i<=y;++i)ans=min(ans,a[i]+tag[p[y]]);
}
return ans;
}
inline int getmax(const int x,const int y){
int ans=-INT_MAX;
if(p[x]==p[y])for(int i=x;i<=y;++i)ans=max(ans,a[i]+tag[p[x]]);
else{
for(int i=x;i<=r[p[x]];++i)ans=max(ans,a[i]+tag[p[x]]);
for(int i=p[x]+1;i<=p[y]-1;++i)ans=max(ans,b[r[i]]+tag[i]);
for(int i=l[p[y]];i<=y;++i)ans=max(ans,a[i]+tag[p[y]]);
}
return ans;
}
inline int getrank(const int x,const int y,const int k){
int cnt=0;
if(p[x]==p[y]){
for(int i=x;i<=y;++i)if(a[i]+tag[p[x]]<=k)cnt++;
}
else{
for(int i=x;i<=r[p[x]];++i)if(a[i]+tag[p[x]]<=k)cnt++;
for(int i=l[p[y]];i<=y;++i)if(a[i]+tag[p[y]]<=k)cnt++;
for(int i=p[x]+1;i<=p[y]-1;++i){
if(b[l[i]]+tag[i]>k)continue;
if(b[r[i]]+tag[i]<=k){
cnt+=r[i]-l[i]+1;
continue;
}
int l1=l[i],r1=r[i],mid;
while(l1<=r1){
mid=(l1+r1)>>1;
if(b[mid]+tag[i]<=k)l1=mid+1;
else r1=mid-1;
}
cnt+=r1-l[i]+1;
}
}
return cnt;
}
inline int query(const int x,const int y,const int k){
if(k<1||k>y-x+1)return -1;
int l1=getmin(x,y),r1=getmax(x,y),mid;
while(l1<=r1){
mid=(l1+r1)>>1;
if(getrank(x,y,mid)<k)l1=mid+1;
else r1=mid-1;
}
return l1;
}
signed main(){
// freopen("P3712.in","r",stdin);
// freopen("P3712.out","w",stdout);
n=read(),m=read(),len=read();
for(int i=2;i<=n;++i){
int u=read();
g[u].push_back(i);
g[i].push_back(u);
c[i]=read();
}
dfs(1,0);
siz1=sqrt(n*__lg(n));
siz1=max(1,siz1);
t=n/siz1;
for(int i=1;i<=t;++i){
l[i]=(i-1)*siz1+1;
r[i]=i*siz1;
}
if(r[t]!=n){
t++;
l[t]=r[t-1]+1;
r[t]=n;
}
for(int i=1;i<=t;++i){
sort(b+l[i],b+r[i]+1);
for(int j=l[i];j<=r[i];++j){
p[j]=i;
}
}
while(m--){
int op=read(),x=read(),k=read();
if(op==1)cout<<query(id[x],id[x]+siz[x]-1,k)<<'\n';
else modify(id[x],id[x]+siz[x]-1,k);
}
return 0;
}