Solution Set - 线段树

A[洛谷P5787]无向图,每条边有一个出现时段,求每个单位时段图是否是二分图。
B[洛谷P5227]无向图,询问删除一个边集后是否连通。
C[洛谷P3733]连通无向图,边有权,加边、修改(增加的边的)边权、删除(增加的边),求边权异或和最大的环的边权异或和。
D[CF981E]初始全零的\(n\)项数列,给定若干区间加的操作,从中任意选出一个子集,求操作后数列的最大值在\(1,2,...,n\)中的可能值。(\(n\le 10^4\)
E[CF603E]无向图,初始没有边,依次加边,边有权,求问是否存在一个边集使得每个点的度均为奇数,如果有,最小化边集内边权最大值。
F[洛谷P4097]维护一个二维平面,支持插入一条线段,询问与某条竖直线相交的所有线段中交点纵坐标最大的一条。
G[洛谷P4027]给定两种金券在\(n\)天内的单价及初始钱数,每一天可以将所有的钱兑换两种金券(两种金券的比例给定),或者卖掉所有金券。求\(n\)天后的最大钱数。
H[CF932F]一棵树,点有两个权值\(a,b\)。从一个点\(u\)可以走到它子树内的点\(v\),代价为\(a_ub_v\)。求每个点到达某个叶子结点的最小代价。
I[洛谷P4655]一个数列,可以删去一些数(开头,结尾除外),代价是保留下的数差分数列的平方和加上每个删除的数的代价(给定),求最小代价。
J[洛谷P4314]维护一个数列,支持区间加,区间覆盖,区间最大值询问,区间历史最大值询问。
K[洛谷P4198]给定若干条形如\((x,0)\sim (x,y)\)的线段,求从\((0,0)\)看去,能看到多少条线段。


线段树分治:将每个操作的影响范围拍到线段树上,然后dfs线段树,统计沿途贡献,在叶子结点记录答案。

A用扩展域的并查集维护,只要用按秩合并、支持删除的并查集即可。
B先算出每条边存在的时间段,丢到线段树上,然后用可撤销的并查集维护。
C用线性基维护。
D容易发现只用考虑这样的子集:其中所有区间有公共点。所以把给定的操作丢到线段树上,在叶子结点用bitset做DP。
E首先发现边集存在等价于每个连通块的点数都是偶数。然后按照边权从小到大加边,在叶子结点往前找到第一个合乎条件的位置,将这些边起作用的范围定为其加入时间到该叶子结点的时间即可。

李超线段树:用线段树维护线段(莫名合理)。每个结点的懒惰标记是一条在该区间中点最优的线段,修改时每次更新都往下搜,至多只有一侧的标记需要更新;单点询问时累计路径上的所有标记。

F模板。
G李超线段树维护斜率优化DP。
H从下往上DP,然后用李超线段树优化。使用李超线段树合并。
I很好写的DP。

J线段树维护历史版本,见oiwiki
K线段树维护单调栈。要求斜率单调递增,合并时向下递归,只会访问一侧。

线段树还是太灵活了。


点击查看A题代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,k,ans[N];
struct edge{int u,v;};
struct disjoint_set{
	int fa[N<<1],sz[N<<1],st[N<<2][2],top;
	void init(){for(int i=1;i<=n*2;i++)fa[i]=i,sz[i]=1;}
	int find(int x){return (fa[x]==x?x:find(fa[x]));}
	void Union(int x,int y){
		int u=find(x),v=find(y);
		if(u==v)return;
		if(sz[u]<sz[v])swap(u,v);
		sz[u]+=sz[v];fa[v]=u;
		st[++top][0]=u;st[top][1]=v;
	}
	void remove(){
		int u=st[top][0],v=st[top][1];--top;
		sz[u]-=sz[v];fa[v]=v;
	}
}S;
struct node{int l,r;vector<edge> e;}tr[N<<2];
void build(int p,int l,int r){
	tr[p].l=l;tr[p].r=r;
	if(l==r)return;
	int mid=l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
}
void modify(int p,int l,int r,edge x){
	if(tr[p].l>=l&&tr[p].r<=r){tr[p].e.push_back(x);return;}
	if(l<=tr[p<<1].r)modify(p<<1,l,r,x);
	if(r>=tr[p<<1|1].l)modify(p<<1|1,l,r,x);
}
void dfs(int p){
	int flag=1,tim=S.top;
	for(auto x:tr[p].e){
		if(S.find(x.u)==S.find(x.v)){
			for(int i=tr[p].l;i<=tr[p].r;i++)
				printf("No\n");
			flag=0;break;
		}
		S.Union(x.u+n,x.v);S.Union(x.u,x.v+n);
	}
	if(flag){
		if(tr[p].l==tr[p].r)printf("Yes\n");
		else dfs(p<<1),dfs(p<<1|1);
	}
	while(S.top>tim)S.remove();
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	build(1,1,k);
	for(int i=1,l,r;i<=m;i++){
		edge e;
		scanf("%d%d%d%d",&e.u,&e.v,&l,&r);
		if(l!=r)modify(1,l+1,r,e);
	}
	S.init();dfs(1);
	return 0;
}
点击查看B题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,k;
struct edge{int u,v;}a[N<<1];
struct disjoint_set{
	int fa[N],sz[N],st[N][2],top;
	void init(int n){for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1;}
	int find(int x){return fa[x]==x?x:find(fa[x]);}
	void Union(int x,int y){
		int u=find(x),v=find(y);
		if(u==v)return;
		if(sz[u]<sz[v])swap(u,v);
		sz[u]+=sz[v];fa[v]=u;
		st[++top][0]=u;st[top][1]=v;
	}
	void remove(){
		int u=st[top][0],v=st[top][1];--top;
		sz[u]-=sz[v];fa[v]=v;
	}
	void clear(int tim){while(top>tim)remove();}
}S;
vector<int> q[N<<1];
struct node{int l,r;vector<int> e;}tr[N<<2];
void build(int p,int l,int r){
	tr[p].l=l;tr[p].r=r;
	if(l==r)return;
	build(p<<1,l,l+r>>1);
	build(p<<1|1,(l+r>>1)+1,r);
}
void modify(int p,int l,int r,int x){
	if(tr[p].l>=l&&tr[p].r<=r){
		tr[p].e.push_back(x);
		return;
	}
	if(l<=tr[p<<1].r)modify(p<<1,l,r,x);
	if(r>=tr[p<<1|1].l)modify(p<<1|1,l,r,x);
}
void dfs(int p){
	int tim=S.top;
	for(auto x:tr[p].e)S.Union(a[x].u,a[x].v);
	if(tr[p].l==tr[p].r)printf(S.top==n-1?"Connected\n":"Disconnected\n");
	else dfs(p<<1),dfs(p<<1|1);
	S.clear(tim);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&a[i].u,&a[i].v);
		q[i].push_back(0);
	}
	scanf("%d",&k);
	for(int i=1,c,d;i<=k;i++){
		scanf("%d",&c);
		while(c--){
			scanf("%d",&d);
			q[d].push_back(i);
		}
	}
	build(1,1,k);
	for(int i=1;i<=m;i++){
		q[i].push_back(k+1);
		for(int j=0;j<q[i].size()-1;j++)
			if(q[i][j]+1<q[i][j+1])modify(1,q[i][j]+1,q[i][j+1]-1,i);
	}
	S.init(n);dfs(1);
	return 0;
}
点击查看C题代码
#include<bits/stdc++.h>
using namespace std;
typedef bitset<1005> BIT;
const int N=1005,len=1000;
struct linear_base{
	BIT p[N];int top,st[N];
	void init(){for(int i=0;i<=len;i++)p[i].reset();top=0;}
	void insert(BIT x){
		for(int i=len;i>=0;i--)if(x[i]){
			if(p[i].none()){st[++top]=i;p[i]=x;return;}
			x^=p[i];
		}
	}
	void query(){
		BIT res;res.reset();
		for(int i=len;i>=0;i--)if(!res[i])res^=p[i];
		for(int i=len,zero=1;i>=0;i--)
			if(!zero||res[i]){cout<<res[i];zero=0;}
		cout<<'\n';
	}
	void remove(){p[st[top]].reset();--top;}
	void clear(int tim){while(top>tim)remove();}
}LB;
int n,m,q,k,vis[N];BIT dep[N];string op,s;
int head[N],nxt[N],ver[N],tot=1,used[N];BIT val[N];
BIT trans(string s){
	BIT res;
	int l=s.size();
	for(int i=0;i<l;i++)res[i]=s[l-1-i]-'0';
	return res;	
}
void add(int u,int v,string s){
	ver[++tot]=v;val[tot]=trans(s);
	nxt[tot]=head[u];head[u]=tot;
}
void dfs(int u){
	vis[u]=1;
	for(int i=head[u],v;i;i=nxt[i])
		if(!vis[v=ver[i]]){used[i]=used[i^1]=1;dep[v]=dep[u]^val[i];dfs(v);}
}
struct edge{int u,v,lst;BIT w;}a[N];
vector<BIT> e[N<<2];
void modify(int p,int l,int r,int L,int R,BIT v){
	if(l>=L&&r<=R){e[p].push_back(v);return;}
	int mid=l+r>>1;
	if(L<=mid)modify(p<<1,l,mid,L,R,v);
	if(R>mid)modify(p<<1|1,mid+1,r,L,R,v);
}
void solve(int p,int l,int r){
	int tim=LB.top;
	for(auto x:e[p])LB.insert(x);
	if(l==r)LB.query();
	else{
		solve(p<<1,l,l+r>>1);
		solve(p<<1|1,(l+r>>1)+1,r);
	}
	LB.clear(tim);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>m>>q;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v>>s;
		add(u,v,s);add(v,u,s);
	}
	dfs(1);LB.init();
	for(int i=1;i<=m;i++)
		if(!used[2*i])LB.insert(dep[ver[2*i]]^dep[ver[2*i+1]]^val[2*i]);
	LB.query();
	if(!q)return 0;
	for(int i=1;i<=q;i++){
		cin>>op;
		if(op[0]=='A'){
			++k;cin>>a[k].u>>a[k].v>>s;
			a[k].lst=i;a[k].w=trans(s)^dep[a[k].u]^dep[a[k].v];
		}
		else if(op[1]=='h'){
			int id;cin>>id>>s;
			modify(1,1,q,a[id].lst,i-1,a[id].w);
			a[id].lst=i;a[id].w=trans(s)^dep[a[id].u]^dep[a[id].v];
		}
		else{
			int id;cin>>id;
			modify(1,1,q,a[id].lst,i-1,a[id].w);a[id].lst=-1;
		}
	}
	for(int i=1;i<=k;i++)
		if(a[i].lst!=-1)modify(1,1,q,a[i].lst,q,a[i].w);
	solve(1,1,q);
	return 0;
}
点击查看D题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
typedef bitset<N> BIT;
int n,q,cnt;BIT ans,now;
vector<int> e[N<<2];
void modify(int p,int l,int r,int L,int R,int x){
	if(l>=L&&r<=R){e[p].push_back(x);return;}
	int mid=l+r>>1;
	if(L<=mid)modify(p<<1,l,mid,L,R,x);
	if(R>mid)modify(p<<1|1,mid+1,r,L,R,x);
}
void solve(int p,int l,int r){
	BIT tmp=now;
	for(auto x:e[p])now|=(now<<x);
	if(l==r)ans|=now;
	else solve(p<<1,l,l+r>>1),
		 solve(p<<1|1,(l+r>>1)+1,r);
	now=tmp;
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1,l,r,x;i<=q;i++){
		scanf("%d%d%d",&l,&r,&x);
		modify(1,1,n,l,r,x);
	}
	now[0]=1;solve(1,1,n);
	for(int i=1;i<=n;i++)cnt+=ans[i];
	printf("%d\n",cnt);
	for(int i=1;i<=n;i++)
		if(ans[i])printf("%d ",i);
	return 0;
}
点击查看E题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,M=3e5+5;
int n,m,k=1,ans[M];
struct edge{int u,v,w,id;}e[M];
bool operator <(edge a,edge b){return a.w<b.w;}
struct disjoint_set{
	int fa[N],sz[N],cnt,st[M][2],top;
	void init(int n){cnt=n;for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1;}
	int find(int x){return (x==fa[x]?x:find(fa[x]));}
	void Union(int x,int y){
		int u=find(x),v=find(y);
		if(u==v)return;
		if(sz[u]<sz[v])swap(u,v);
		if(sz[u]&1)--cnt;if(sz[v]&1)--cnt;
		sz[u]+=sz[v];fa[v]=u;if(sz[u]&1)++cnt;
		st[++top][0]=u;st[top][1]=v;
	}
	void remove(){
		int u=st[top][0],v=st[top][1];--top;
		if(sz[u]&1)--cnt;sz[u]-=sz[v];fa[v]=v;
		if(sz[u]&1)++cnt;if(sz[v]&1)++cnt;
	}
	void clear(int tim){while(top>tim)remove();}
}S;
vector<int> q[M<<2];
void modify(int p,int l,int r,int L,int R,int x){
	if(l>=L&&r<=R){q[p].push_back(x);return;}
	int mid=l+r>>1;
	if(L<=mid)modify(p<<1,l,mid,L,R,x);
	if(R>mid)modify(p<<1|1,mid+1,r,L,R,x);
}
void solve(int p,int l,int r){
	int tim=S.top;
	for(auto x:q[p])S.Union(e[x].u,e[x].v);
	if(l==r){
		for(;k<=m&&S.cnt;k++)if(e[k].id<=l){
			S.Union(e[k].u,e[k].v);
			if(e[k].id!=l)modify(1,1,m,e[k].id,l-1,k);
		}
		if(S.cnt)ans[l]=-1;else ans[l]=e[k-1].w;
	}
	else solve(p<<1|1,(l+r>>1)+1,r),
		 solve(p<<1,l,l+r>>1);
	S.clear(tim);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w),e[i].id=i;
	sort(e+1,e+m+1);S.init(n);solve(1,1,m);
	for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
	return 0;
}
点击查看F题代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<double,int> pdi;
const int N=1e5+5,M=39989,M0=1e9;
const double eps=1e-9;
int n,cnt,tr[M<<2+10];
struct line{double k,b;}p[N];
double calc(int id,int x){return p[id].b+p[id].k*x;}
int cmp(double x,double y){
	if(x-y>eps)return 1;
	if(y-x>eps)return -1;
	return 0;
}
void push_down(int p,int l,int r,int u){
	int &v=tr[p],mid=l+r>>1;
	if(cmp(calc(u,mid),calc(v,mid))==1)swap(u,v);
	int bl=cmp(calc(u,l),calc(v,l)),br=cmp(calc(u,r),calc(v,r));
	if(bl==1||(!bl&&u<v))push_down(p<<1,l,mid,u);
	if(br==1||(!br&&u<v))push_down(p<<1|1,mid+1,r,u);
}
void modify(int p,int l,int r,int L,int R,int u){
	if(l>=L&&r<=R){push_down(p,l,r,u);return;}
	int mid=l+r>>1;
	if(L<=mid)modify(p<<1,l,mid,L,R,u);
	if(R>mid)modify(p<<1|1,mid+1,r,L,R,u);
}
pdi pmax(pdi x,pdi y){
	if(cmp(x.first,y.first)==-1)return y;
	if(cmp(x.first,y.first)==1)return x;
	return x.second<y.second?x:y;
}
pdi query(int p,int l,int r,int x){
	if(r<x||x<l)return {0,0};
	int mid=l+r>>1;double res=calc(tr[p],x);
	if(l==r)return {res,tr[p]};
	return pmax({res,tr[p]},pmax(query(p<<1,l,mid,x),
								query(p<<1|1,mid+1,r,x)));
}
int main(){
	scanf("%d",&n);
	for(int i=1,op,lstans=0;i<=n;i++){
		scanf("%d",&op);
		if(op==0){
			int x;scanf("%d",&x);
			x=(x+lstans-1)%M+1;
			lstans=query(1,1,M,x).second;
			printf("%d\n",lstans);
		}
		else{
			int x0,y0,x1,y1;++cnt;
			scanf("%d%d%d%d",&x0,&y0,&x1,&y1);
			x0=(x0+lstans-1)%M+1;
			x1=(x1+lstans-1)%M+1;
			y0=(y0+lstans-1)%M0+1;
			y1=(y1+lstans-1)%M0+1;
			if(x0>x1)swap(x0,x1),swap(y0,y1);
			if(x0==x1)p[cnt].k=0,p[cnt].b=max(y0,y1);
			else p[cnt].k=1.0*(y1-y0)/(x1-x0),p[cnt].b=y0-p[cnt].k*x0;
			modify(1,1,M,x0,x1,cnt);
		}
	}
	return 0;
}
点击查看G题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n;double a[N],b[N],r[N],x[N],dp[N];
struct line{
	double k,b;
	double f(double x){return k*x+b;}
};
struct LCST{
	//Li Chao's Segment Tree
	line tr[N<<2];
	void push_down(int p,int l,int r,line u){
		line &v=tr[p];int mid=l+r>>1;
		if(u.f(x[mid])>v.f(x[mid]))swap(u,v);
		if(u.f(x[l])>v.f(x[l]))push_down(p<<1,l,mid,u);
		if(u.f(x[r])>v.f(x[r]))push_down(p<<1|1,mid+1,r,u);
	}
	void modify(int p,int l,int r,int L,int R,line u){
		if(l>=L&&r<=R){push_down(p,l,r,u);return;}
		int mid=l+r>>1;
		if(L<=mid)modify(p<<1,l,mid,L,R,u);
		if(R>mid)modify(p<<1|1,mid+1,r,L,R,u);
	}
	line query(int p,int l,int r,int v){
		if(l==r)return tr[p];
		int mid=l+r>>1;line res=tr[p],tmp;
		if(v<=mid)tmp=query(p<<1,l,mid,v);
		else tmp=query(p<<1|1,mid+1,r,v);
		if(tmp.f(x[v])>res.f(x[v]))res=tmp;
		return res;
	}
}seg;
int main(){
	scanf("%d%lf",&n,dp);
	for(int i=1;i<=n;i++)
		scanf("%lf%lf%lf",a+i,b+i,r+i),x[i]=a[i]/b[i];
	sort(x+1,x+n+1);
	for(int i=1;i<=n;i++){
		double t=a[i]/b[i];
		int pos=lower_bound(x+1,x+n+1,t)-x;
		dp[i]=max(dp[i-1],seg.query(1,1,n,pos).f(t)*b[i]);
		line u;u.b=dp[i]/(a[i]*r[i]+b[i]);u.k=u.b*r[i];
		seg.push_down(1,1,n,u);
	}
	printf("%.3lf\n",dp[n]);
	return 0;
}
点击查看H题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
bool mem1;
struct line{
	ll k,b;
	ll f(ll x){return k*x+b;}
	line(ll k0=0,ll b0=1e12){k=k0;b=b0;}
}zero;
struct LCST{
	line tr[N*60];int lc[N*60],rc[N*60],tot;
	void push_down(int p,int l,int r,line u){
		line &v=tr[p];int mid=l+r>>1;
		if(u.f(mid)<v.f(mid))swap(u,v);
		if(u.f(l)<v.f(l)){
			if(!lc[p])lc[p]=++tot;
			push_down(lc[p],l,mid,u);
		}
		if(u.f(r)<v.f(r)){
			if(!rc[p])rc[p]=++tot;
			push_down(rc[p],mid+1,r,u);
		}
	}
	line query(int p,int l,int r,int x){
		if(!p)return zero;
		if(l==r)return tr[p];
		int mid=l+r>>1;line res=tr[p],tmp;
		if(x<=mid)tmp=query(lc[p],l,mid,x);
		else tmp=query(rc[p],mid+1,r,x);
		if(tmp.f(x)<res.f(x))res=tmp;
		return res;
	}
	int merge(int p,int q,int l,int r){
		if(!p)return q;
		if(!q)return p;
		if(l==r)return tr[p].f(l)<tr[q].f(l)?p:q;
		int mid=l+r>>1;
		lc[p]=merge(lc[p],lc[q],l,mid);
		rc[p]=merge(rc[p],rc[q],mid+1,r);
		push_down(p,l,r,tr[q]);
		return p;
	}
}seg;
int n,a[N],b[N],root[N];ll dp[N];
int head[N],nxt[N<<1],ver[N<<1],tot;
void add(int u,int v){ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
void dfs(int u,int fa){
	root[u]=++seg.tot;
	if(!nxt[head[u]]&&fa!=-1){
		seg.push_down(root[u],-1e5,1e5,{b[u],0});
		return;
	}
	for(int i=head[u],v;i;i=nxt[i])
		if((v=ver[i])!=fa){
			dfs(v,u);
			root[u]=seg.merge(root[u],root[v],-1e5,1e5);
		}
	dp[u]=seg.query(root[u],-1e5,1e5,a[u]).f(a[u]);
	seg.push_down(root[u],-1e5,1e5,{b[u],dp[u]});
}
bool mem2;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",a+i);
	for(int i=1;i<=n;i++)scanf("%d",b+i);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
	dfs(1,-1);
	for(int i=1;i<=n;i++)printf("%lld ",dp[i]);
	return 0;
}
点击查看I题代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
const ll INF=1ll<<50;
struct line{
	ll k,b;
	ll f(ll x){return k*x+b;}
	line(ll k0=0,ll b0=-INF){k=k0,b=b0;}
};
struct LCST{
	line tr[N<<2];int lc[N<<2],rc[N<<2],tot;
	void push_down(int p,int l,int r,line u){
		line &v=tr[p];int mid=l+r>>1;
		if(u.f(mid)>v.f(mid))swap(u,v);
		if(u.f(l)>v.f(l)){
			if(!lc[p])lc[p]=++tot;
			push_down(lc[p],l,mid,u);
		}
		if(u.f(r)>v.f(r)){
			if(!rc[p])rc[p]=++tot;
			push_down(rc[p],mid+1,r,u);
		}
	}
	ll query(int p,int l,int r,int x){
		if(!p)return -INF;
		if(l==r)return tr[p].f(x);
		int mid=l+r>>1;ll res=tr[p].f(x);
		if(x<=mid)res=max(res,query(lc[p],l,mid,x));
		else res=max(res,query(rc[p],mid+1,r,x));
		return res;
	}
}seg;
int n;ll h[N],s[N],dp[N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lld",h+i);
	for(int i=1,w;i<=n;i++)scanf("%d",&w),s[i]=s[i-1]+w;
	dp[1]=0;seg.tot=1;seg.push_down(1,0,1e6,{2*h[1],s[1]-h[1]*h[1]});
	for(int i=2;i<=n;i++){
		dp[i]=s[i-1]+h[i]*h[i]-seg.query(1,0,1e6,h[i]);
		seg.push_down(1,0,1e6,{2*h[i],s[i]-h[i]*h[i]-dp[i]});
	}
	printf("%lld\n",dp[n]);
	return 0;
}
点击查看J题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,a[N];char op;
struct node{int mx,mxh,tag,tagh,st,sth;}tr[N<<2];
void push_up(int p){
	tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
	tr[p].mxh=max(tr[p<<1].mxh,tr[p<<1|1].mxh);
}
void push_add(int p,int v,int vh){
	tr[p].mxh=max(tr[p].mxh,tr[p].mx+vh);tr[p].mx+=v;
	if(tr[p].st==INT_MIN)tr[p].tagh=max(tr[p].tagh,tr[p].tag+vh),tr[p].tag+=v;
	else tr[p].sth=max(tr[p].sth,tr[p].st+vh),tr[p].st+=v;
}
void push_set(int p,int v,int vh){
	tr[p].mxh=max(tr[p].mxh,vh);tr[p].mx=v;
	tr[p].sth=max(tr[p].sth,vh);tr[p].st=v;
}
void push_down(int p,int l,int r){
	if(tr[p].tag||tr[p].tagh){
		push_add(p<<1,tr[p].tag,tr[p].tagh);
		push_add(p<<1|1,tr[p].tag,tr[p].tagh);
		tr[p].tag=tr[p].tagh=0;
	}
	if(tr[p].st!=INT_MIN||tr[p].sth!=INT_MIN){
		push_set(p<<1,tr[p].st,tr[p].sth);
		push_set(p<<1|1,tr[p].st,tr[p].sth);
		tr[p].st=tr[p].sth=INT_MIN;
	}
}
#define mid (l+r>>1)
void build(int p,int l,int r){
	tr[p].st=tr[p].sth=INT_MIN;
	if(l==r){tr[p].mx=tr[p].mxh=a[l];return;}
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	push_up(p);
}
void madd(int p,int l,int r,int L,int R,int v){
	if(l>=L&&r<=R){push_add(p,v,max(v,0));return;}
	push_down(p,l,r);
	if(L<=mid)madd(p<<1,l,mid,L,R,v);
	if(R>mid)madd(p<<1|1,mid+1,r,L,R,v);
	push_up(p);
}
void mset(int p,int l,int r,int L,int R,int v){
	if(l>=L&&r<=R){push_set(p,v,v);return;}
	push_down(p,l,r);
	if(L<=mid)mset(p<<1,l,mid,L,R,v);
	if(R>mid)mset(p<<1|1,mid+1,r,L,R,v);
	push_up(p);
}
int qmax(int p,int l,int r,int L,int R){
	if(l>=L&&r<=R)return tr[p].mx;
	push_down(p,l,r);
	int res=INT_MIN;
	if(L<=mid)res=max(qmax(p<<1,l,mid,L,R),res);
	if(R>mid)res=max(qmax(p<<1|1,mid+1,r,L,R),res);
	return res;
}
int qmaxh(int p,int l,int r,int L,int R){
	if(l>=L&&r<=R)return tr[p].mxh;
	push_down(p,l,r);
	int res=INT_MIN;
	if(L<=mid)res=max(qmaxh(p<<1,l,mid,L,R),res);
	if(R>mid)res=max(qmaxh(p<<1|1,mid+1,r,L,R),res);
	return res;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",a+i);
	build(1,1,n);
	scanf("%d",&m);
	for(int i=1,x,y,z;i<=m;i++){
		while(op=getchar(),op!='Q'&&op!='A'&&op!='P'&&op!='C');
		switch(op){
			case 'Q':{scanf("%d%d",&x,&y);printf("%d\n",qmax(1,1,n,x,y));break;}
			case 'A':{scanf("%d%d",&x,&y);printf("%d\n",qmaxh(1,1,n,x,y));break;}
			case 'P':{scanf("%d%d%d",&x,&y,&z);madd(1,1,n,x,y,z);break;}
			case 'C':{scanf("%d%d%d",&x,&y,&z);mset(1,1,n,x,y,z);break;}
		}
	}
	return 0;
}
点击查看K题代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m;
struct node{double mx;int len;}tr[N<<2];
int query(int p,int l,int r,double x){
	if(l==r)return tr[p].mx>x;
	int mid=l+r>>1;
	if(tr[p<<1].mx>x)return query(p<<1,l,mid,x)+tr[p<<1|1].len;
	else return query(p<<1|1,mid+1,r,x);
}
void modify(int p,int l,int r,int x,double v){
	if(l==r){tr[p].mx=v;tr[p].len=1;return;}
	int mid=l+r>>1;
	if(x<=mid)modify(p<<1,l,mid,x,v);
	else modify(p<<1|1,mid+1,r,x,v);
	tr[p<<1|1].len=query(p<<1|1,mid+1,r,tr[p<<1].mx);
	tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,x,y;i<=m;i++){
		scanf("%d%d",&x,&y);
		modify(1,1,n,x,1.0*y/x);
		printf("%d\n",query(1,1,n,0));
	}
	return 0;
}
posted @ 2023-05-24 21:15  by_chance  阅读(17)  评论(0编辑  收藏  举报