Loading

noip模拟46

A. 数数

签到题.

A_code


#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int 
	#define ull unsigend ll
	#define re register ll 
	#define lf double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	inline ll read() {
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=3e5+51;

ll m,n,minn,maxn;
ll w[N];
struct I { ll minn,maxn,num; } tr[N<<4];
inline void Init(){
	n=read(); minn=1e7,maxn=-1e7;
	for(re i=1;i<=n;++i) 
		w[i]=read(),minn=min(minn,w[i]);
	if(minn<=0){
		for(re i=1;i<=n;++i) 
			w[i]+=abs(minn)+1,maxn=max(maxn,w[i]);
	}
	else{
		for(re i=1;i<=n;++i) maxn=max(maxn,w[i]);
	}
	return ;
}
inline void pushup(ll x){
	tr[x].num=tr[x<<1].num+tr[x<<1|1].num,
	tr[x].minn=min(tr[x<<1].minn,tr[x<<1|1].minn),
	tr[x].maxn=max(tr[x<<1].maxn,tr[x<<1|1].maxn);
	return ;
}
void update(ll x,ll l,ll r,ll pos,ll num){
	if(l==r){
		tr[x].num+=num;
		if(tr[x].num) tr[x].minn=l,tr[x].maxn=l;
		else tr[x].minn=1e7,tr[x].maxn=-1;
		return ;
	}
	ll mid=(l+r)>>1;
	if(pos<=mid) update(x<<1,l,mid,pos,num);
	else update(x<<1|1,mid+1,r,pos,num);
	pushup(x); return ;
}
void build(ll x,ll l,ll r){
	if(l==r){
		tr[x].minn=1e7,tr[x].maxn=-1;
		return ;
	}
	ll mid=(l+r)>>1;
	build(x<<1,l,mid),build(x<<1|1,mid+1,r);
	pushup(x); return ;
}
inline void Work(){
	build(1,1,maxn);
	for(re i=1;i<=n;++i) update(1,1,maxn,w[i],1);
	puts("0"); ll x,y,ans=0,res=0;
	for(re i=2;i<=n-1;i+=2){
		x=tr[1].minn,y=tr[1].maxn;
		update(1,1,maxn,x,-1),update(1,1,maxn,y,-1);
		printf("%lld\n%lld\n",abs(y-x)+ans+res,2*abs(y-x)+2*res+ans);
		ans+=((abs(y-x)+res)<<1),res+=abs(y-x);
	}
	x=tr[1].minn,y=tr[1].maxn;
	if((n&1)^1) printf("%lld\n",ans+res+abs(y-x));
	return ;
}
signed main(){
	Init();
	Work();
	exit(0);
}

B. 数树

C. 鼠树

发现这个题实现起来很复杂,

权值转移地很频繁,

所以可以把权值存得更间接、简洁一些.

因为想学线段树分裂,所以这里打的是线段树分裂.

C_code


#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll unsigned int 
	#define re register ll 
	#define lf double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	inline ll read() {
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=6e5+51;

ll n,m,ops,cnt,now,ts;
ll rt[N],dfn[N],siz[N],rk[N],son[N],fa[N],top[N],dep[N],head[N];
struct I { ll u,v,nxt; } e[N];
set<ll> s;
inline void add(ll u,ll v){
	e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u],
	head[u]=ts;
}
struct Tree_Array {
	ll res,tmp; ll a[N<<3],b[N<<3],c[N<<3];
	inline void update1(ll x,ll w){ for(;x<=n;x+=lbt(x)) a[x]+=w; }
	inline void update2(ll x,ll w){ tmp=x*w; for(;x<=n;x+=lbt(x)) b[x]+=w,c[x]+=tmp; }
	inline ll query1(ll x){ res=0,tmp=x; for(;x;x&=x-1) res+=a[x],res+=(tmp+1)*b[x],res-=c[x]; return res; }
	inline ll query2(ll x){ res=0,tmp=x; for(;x;x&=x-1) res+=(tmp+1)*b[x],res-=c[x]; return res; }
} A;
struct Segment {
	ll tot,tail; ll skt[N<<3];
	struct II { ll w,ls,rs,lzy,sz; } tr[N<<3];
	inline void reg(ll &x){ skt[++tail]=x,x=0; }
	inline void get(ll &x){ x=(tail?skt[tail--]:++tot); tr[x].w=0,tr[x].ls=0,tr[x].rs=0,tr[x].lzy=0; }
	inline void pushup(ll x){ tr[x].w=tr[tr[x].ls].w+tr[tr[x].rs].w,tr[x].sz=tr[tr[x].ls].sz+tr[tr[x].rs].sz; }
	inline void spread(ll x){
		if(!tr[x].lzy) return ;
		ll ls=tr[x].ls,rs=tr[x].rs,&lzy=tr[x].lzy;
		tr[ls].w+=lzy*tr[ls].sz,tr[rs].w+=lzy*tr[rs].sz,tr[ls].lzy+=lzy,tr[rs].lzy+=lzy,lzy=0;
	}
	void build(ll &x,ll l,ll r){
		get(x); tr[x].sz=(r-l+1);
		if(l==r) return ; ll mid=(l+r)>>1;
		build(tr[x].ls,l,mid),build(tr[x].rs,mid+1,r);
	}
	void merge(ll &x,ll &y,ll l,ll r){
		if((!x) or (!y)) return x=x+y,void();
		spread(x),spread(y);ll mid=(l+r)>>1;
		merge(tr[x].ls,tr[y].ls,l,mid),merge(tr[x].rs,tr[y].rs,mid+1,r);
		pushup(x); reg(y);
	}
	void split(ll &x,ll &y,ll l,ll r,ll ql,ll qr){
		if(!x) return ;  
		if(l>=ql and r<=qr) return y=x,x=0,void();
		get(y); spread(x); ll mid=(l+r)>>1;
		if(ql<=mid) split(tr[x].ls,tr[y].ls,l,mid,ql,qr);
		if(qr>mid) split(tr[x].rs,tr[y].rs,mid+1,r,ql,qr);
		pushup(x),pushup(y); if(!tr[x].sz) reg(x);
	}
	void update(ll x,ll l,ll r,ll ql,ll qr,ll w){
		if(!x) return;
		if(l>=ql and r<=qr) return tr[x].w+=tr[x].sz*w,tr[x].lzy+=w,A.update1(dfn[now],tr[x].sz*w),void();
		spread(x);ll mid=(l+r)>>1;
		if(ql<=mid) update(tr[x].ls,l,mid,ql,qr,w);
		if(qr>mid) update(tr[x].rs,mid+1,r,ql,qr,w);
		pushup(x);
	}
	ll query(ll x,ll l,ll r,ll ql,ll qr){
		if(!x) return 0; if(l>=ql and r<=qr) return tr[x].w;
		spread(x); ll res=0; ll mid=(l+r)>>1;
		if(ql<=mid) res+=query(tr[x].ls,l,mid,ql,qr);
		if(qr>mid) res+=query(tr[x].rs,mid+1,r,ql,qr);
		pushup(x); return res;
	}
} B;
void dfs1(ll u,ll dad,ll depth){
	dep[u]=depth,fa[u]=dad,siz[u]=1;
	for(re i=head[u];i;i=e[i].nxt){
		dfs1(e[i].v,u,depth+1);
		siz[u]+=siz[e[i].v];
		if(siz[son[u]]<siz[e[i].v]){
			son[u]=e[i].v;
		}
	}
}
void dfs2(ll u,ll high){
	dfn[u]=++cnt,rk[cnt]=u,top[u]=high;
	if(!son[u]) return ;
	dfs2(son[u],high);
	for(re i=head[u];i;i=e[i].nxt){
		if(e[i].v==son[u]) continue;
		dfs2(e[i].v,e[i].v);
	}
}
inline ll find(ll x){
	while(1){
		ll dad=*--s.upper_bound(dfn[x]);
		if(dad>=dfn[top[x]]) return rk[dad];
		x=fa[top[x]];
	}
}
inline ll ask(ll x){ return A.query2(dfn[x])-A.query2(dfn[x]-1)+B.query(rt[find(x)],1,n,dfn[x],dfn[x]); }
signed main(){
	n=read(),ops=read(); ll u,v,w,opt,res;
	for(re i=2;i<=n;i++) v=read(),add(v,i);
	dfs1(1,0,0),dfs2(1,1); s.insert(1),B.build(rt[1],1,n);
	while(ops--){	
		opt=read(),u=read(),now=u;
		if(opt==1) printf("%u\n",ask(u));
		else if(opt==2) w=read(),B.update(rt[u],1,n,1,n,w);
		else if(opt==3){
			v=find(u),now=v,res=A.query1(dfn[u]+siz[u]-1)-A.query1(dfn[u]-1);
			if(u!=v) res+=B.query(rt[v],1,n,dfn[u],dfn[u]+siz[u]-1);
			printf("%u\n",res);
		}
		else if(opt==4){
			w=read(); A.update2(dfn[u],w),A.update2(dfn[u]+siz[u],-w);
			v=find(u),now=v;
			if(u!=v) B.update(rt[v],1,n,dfn[u],dfn[u]+siz[u]-1,-w);
		}
		else if(opt==5){
			s.insert(dfn[u]),v=find(fa[u]); B.split(rt[v],rt[u],1,n,dfn[u],dfn[u]+siz[u]-1);
			w=B.tr[rt[u]].w; A.update1(dfn[u],w),A.update1(dfn[v],-w);
		}
		else if(opt==6){
			s.erase(dfn[u]); w=B.tr[rt[u]].w;
			v=find(fa[u]); B.merge(rt[v],rt[u],1,n);
			A.update1(dfn[u],-w),A.update1(dfn[v],w);
		}
	}
	exit(0);
}

D. ckw 的树

posted @ 2021-09-10 15:54  AaMuXiiiiii  阅读(48)  评论(0)    收藏  举报