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;
}

posted @ 2022-02-14 15:16  myee  阅读(52)  评论(0编辑  收藏  举报