专栏文章
Solution P14380 | Easy Data Structure
P14380题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mincxjl3
- 此快照首次捕获于
- 2025/12/02 00:22 3 个月前
- 此快照最后确认于
- 2025/12/02 00:22 3 个月前
若 且 ,将 视作极小区间。问题转化为计算 中有多少个极小区间。
对于每个 求出最大的 使得 ,记作 ;同时求出最小的 使得 ,记作 。
那么极小区间的判定变成了 且 。
令 表示 是否极小。查询可以看作在 上矩形求和。用二维前缀和拆掉考虑。
对 扫描线,用历史和线段树维护即可。
CPPint n,q,dfn[500005],out[500005],tim,al[500005],ar[500005],l[500005],r[500005];
vector<int>E[500005];
void dfs(int x,int fa){
dfn[x]=(++tim);
for(auto y: E[x]){
if(y==fa) continue;
dfs(y,x);
}
out[x]=tim;
}
void chkmax(int &a,int b){ if(b>a) a=b; }
namespace zkw{
int n,c[2000005];
void init(int _n){
for(n=1;n<_n;n<<=1);
for(int i=0;i<(n<<1);i++) c[i]=0;
}
void upd(int x,int w){
for(x+=n-1;x;x>>=1) chkmax(c[x],w);
}
int qry(int l,int r){
int ret=0;
for(l+=n-1,r+=n;l<r;l>>=1,r>>=1){
if(l&1) chkmax(ret,c[l++]);
if(r&1) chkmax(ret,c[--r]);
}
return ret;
}
}
namespace seg{
int cnt[2000005],tag[2000005]; ll val[2000005];
void upd(int pos,int v){
tag[pos]+=v;
val[pos]+=1ull*v*cnt[pos];
}
void pushdown(int pos){
if(tag[pos]){
upd(pos<<1, tag[pos]), upd(pos<<1|1, tag[pos]);
tag[pos]=0;
}
}
void pushup(int pos){
val[pos]=val[pos<<1]+val[pos<<1|1];
cnt[pos]=cnt[pos<<1]+cnt[pos<<1|1];
}
void update(int l,int r,int ql,int qr,int pos){
if(qr<l || r<ql) return;
if(ql<=l && r<=qr){
upd(pos, 1);
return;
}
int mid=(l+r)>>1; pushdown(pos);
update(l,mid,ql,qr,pos<<1);
update(mid+1,r,ql,qr,pos<<1|1);
pushup(pos);
}
void modify(int l,int r,int x,int s,int pos){
if(l==r){ cnt[pos]=s; return; }
int mid=(l+r)>>1; pushdown(pos);
if(x<=mid) modify(l,mid,x,s,pos<<1);
else modify(mid+1,r,x,s,pos<<1|1);
pushup(pos);
}
ll query(int l,int r,int ql,int qr,int pos){
if(qr<l || r<ql) return 0;
if(ql<=l && r<=qr) return val[pos];
int mid=(l+r)>>1; pushdown(pos);
return query(l,mid,ql,qr,pos<<1)+query(mid+1,r,ql,qr,pos<<1|1);
}
}
vector<int>vec[500005];
vector<pair<int,int>>qry[500005];
ll ans[500005];
void procedure(){
n=read(),q=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
E[x].pb(y), E[y].pb(x);
}
dfs(1,0);
zkw::init(n);
for(int i=1;i<=n;i++){
vector<int>cur;
for(auto j: E[i]){
if(dfn[j]<dfn[i]) cur.pb(max(zkw::qry(1,dfn[i]-1),zkw::qry(out[i]+1,n)));
else cur.pb(zkw::qry(dfn[j],out[j]));
}
if(cur.size()>=2){
sort(cur.begin(), cur.end(), greater<int>());
al[i]=cur[1]+1;
}else al[i]=1;
zkw::upd(dfn[i],i);
}
zkw::init(n);
for(int i=n;i>=1;i--){
vector<int>cur;
for(auto j: E[i]){
if(dfn[j]<dfn[i]) cur.pb(max(zkw::qry(1,dfn[i]-1),zkw::qry(out[i]+1,n)));
else cur.pb(zkw::qry(dfn[j],out[j]));
}
if(cur.size()>=2){
sort(cur.begin(), cur.end(), greater<int>());
ar[i]=n-cur[1];
}else ar[i]=n;
zkw::upd(dfn[i],n-i+1);
vec[i].pb(i), vec[ar[i]+1].pb(-i);
}
for(int i=1;i<=q;i++){
l[i]=read(),r[i]=read();
qry[l[i]-1].pb(l[i]-1,i), qry[l[i]-1].pb(r[i],-i);
qry[r[i]].pb(l[i]-1,-i), qry[r[i]].pb(r[i],i);
}
for(int r=1;r<=n;r++){
for(auto x: vec[r]){
if(x>0) seg::modify(1,n,x,1,1);
else seg::modify(1,n,-x,0,1);
}
seg::update(1,n,al[r],r,1);
for(auto [x,y]: qry[r]){
ll val=seg::query(1,n,1,x,1);
if(y>0) ans[y]+=val;
else ans[-y]-=val;
}
}
for(int i=1;i<=q;i++){
printf("%lld\n",ans[i]);
}
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...