bzoj4765
同见于 Hydro-bzoj
思路
为什么这题机房内部、网上人均分块啊......
注意到转成括号序后是 [Ynoi2077] 3dmq 的严格弱化版,甚至也是 "2dmq" 的弱化版,于是乎你可以暴力用严格 \(O(n\sqrt n)\) 的 kdt。
嘴巴一下如何优化复杂度。
对左右括号分讨,可以转换为矩形加矩形查询,并且矩形加有一维无界,矩形求和另一维无界。
于是这题(似乎)可以 polylog 了。其实我也不会,是嘴巴的。
打了一个 kdt 的版本,时限 3s,在 Hydro-bzoj 很容易就过了。
polylog 做法有兴趣的同学自行实现吧。
Code
#include <algorithm>
#include <stdio.h>
#include <vector>
typedef long long llt;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;}
template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;}
template<typename T>T power(T base,T index,T mod){return((index<=1)?(index?base:1):(power(base*base%mod,index>>1,mod)*power(base,index&1,mod)))%mod;}
template<typename T>T lowbit(T n){return n&-n;}
template<typename T>T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<typename T>T lcm(T a,T b){return(a!=0||b!=0)?a/gcd(a,b)*b:(T)0;}
template<typename T>T exgcd(T a,T b,T&x,T&y){if(!b)return y=0,x=1,a;T ans=exgcd(b,a%b,y,x);y-=a/b*x;return ans;}
struct point{uint x,y;ullt a,v;};
struct node
{
point p;uint Maxx,Minx,Maxy,Miny;ullt sum,lazy,suma;node*L,*R;
node(point*bgn,point*end,bol op):lazy(0),L(NULL),R(NULL)
{
point*mid=bgn+((end-bgn)>>1);
std::nth_element(bgn,mid,end,[=](point a,point b){return op?a.x<b.x:a.y<b.y;});
p=*mid,Maxx=Minx=p.x,Maxy=Miny=p.y,sum=p.v,suma=p.a;
if(bgn!=mid)L=new node(bgn,mid,!op),
_max(Maxx,L->Maxx),_max(Maxy,L->Maxy),
_min(Minx,L->Minx),_min(Miny,L->Miny),
sum+=L->sum,suma+=L->suma;
if(mid+1!=end)R=new node(mid+1,end,!op),
_max(Maxx,R->Maxx),_max(Maxy,R->Maxy),
_min(Minx,R->Minx),_min(Miny,R->Miny),
sum+=R->sum,suma+=R->suma;
}
voi pushdown()
{
if(L!=NULL)L->sum+=lazy*L->suma,L->lazy+=lazy,L->p.v+=lazy*L->p.a;
if(R!=NULL)R->sum+=lazy*R->suma,R->lazy+=lazy,R->p.v+=lazy*R->p.a;
lazy=0;
}
voi pushup()
{
pushdown(),sum=p.v;
if(L!=NULL)sum+=L->sum;
if(R!=NULL)sum+=R->sum;
}
voi add(uint r,ullt w)
{
if(Minx>r)return;
if(Maxx<=r){lazy+=w,p.v+=w*p.a,sum+=w*suma;return;}
if(p.x<=r)p.v+=w*p.a;
if(L!=NULL)L->add(r,w);
if(R!=NULL)R->add(r,w);
pushup();
}
ullt find(uint l,uint r)
{
if(Miny>=r||Maxy<l)return 0;
if(Miny>=l&&Maxy<r)return sum;
pushdown();
ullt ans=0;
if(p.y>=l&&p.y<r)ans=p.v;
if(L!=NULL)ans+=L->find(l,r);
if(R!=NULL)ans+=R->find(l,r);
return ans;
}
};
std::vector<uint>Way[300005];ullt A[300005];point P[300005];uint Dfn[300005];
uint cnt;
voi dfs(uint p,uint f)
{
P[p<<1].x=Dfn[p]=cnt++,P[p<<1].v=A[p];
for(auto s:Way[p])if(s!=f)dfs(s,p),P[p<<1].v+=P[s<<1].v;
P[p<<1|1].x=cnt++;
}
int main()
{
uint n,m,rt=0;scanf("%u%u",&n,&m);
for(uint i=0;i<n;i++)scanf("%llu",A+i),P[i<<1].y=P[i<<1|1].y=i,P[i<<1].a=1llu,P[i<<1|1].a=-1llu;
for(uint i=0;i<n;i++){uint u,v;scanf("%u%u",&u,&v);if(u)Way[--u].push_back(--v),Way[v].push_back(u);else rt=v-1;}
dfs(rt,-1);
node T(P,P+(n<<1),0);
while(m--)
{
uint op;scanf("%u",&op);
if(op==1){uint p;ullt v;scanf("%u%llu",&p,&v),p--;T.add(Dfn[p],v-A[p]),A[p]=v;}
else{uint l,r;scanf("%u%u",&l,&r),printf("%llu\n",T.find(l-1,r));}
}
return 0;
}
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/bzoj4765.html