码迷,mamicode.com
首页 > 其他好文 > 详细

联考20200525 T1 数据结构

时间:2020-05-25 22:30:32      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:using   void   printf   bool   ring   转化   标记   int()   str   

技术图片
技术图片
技术图片

分析:
这道题可以看做单点修改区间查询历史最小值的数据结构题
区间修改单点查询历史版本可以使用二维数据结构维护
由于卡空间,这里只能选择KD树
在KD树上区间修改,历史最值只需要统计单点到根节点的路径上记录的历史最值就行了
关键是这道题如何转化?
我们把询问离线,每一个查询\((l,r)\)看做坐标轴上的单点
单点\(x\)的修改可以看做对横坐标为\([1,x]\)纵坐标\([x,n]\)的矩形区间修改
于是转化成了区间修改单点查询
KD树上每个节点存储当前状态和懒标记状态(状态包含当前值和历史最值)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>

#define maxn 200005
#define INF 0x3f3f3f3f

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1;
	while(c>=‘0‘&&c<=‘9‘)num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,m,N,rt;
int a[maxn],op[maxn],x[maxn],y[maxn],id[maxn];
long long sum[maxn];
struct data{
	long long num,mn;
	data(){}data(long long x){num=mn=x;}
	inline void update(data p){mn=min(mn,num+p.mn),num+=p.num;}
};
struct node{
	int d[2],mn[2],mx[2],ch[2],fa;
	data val,lz;
}t[maxn];
inline bool cmp0(int x,int y){return t[x].d[0]<t[y].d[0];}
inline bool cmp1(int x,int y){return t[x].d[1]<t[y].d[1];}
inline void update(node &p)
{
	p.mn[0]=p.mx[0]=p.d[0],p.mn[1]=p.mx[1]=p.d[1];
	for(int i=0;i<2;i++)if(p.ch[i])for(int j=0;j<2;j++)
		p.mn[j]=min(p.mn[j],t[p.ch[i]].mn[j]),p.mx[j]=max(p.mx[j],t[p.ch[i]].mx[j]);
}
inline void pushdown(int i)
{
	if(t[i].lz.mn||t[i].lz.num)
	{
		if(t[i].ch[0])t[t[i].ch[0]].val.update(t[i].lz),t[t[i].ch[0]].lz.update(t[i].lz);
		if(t[i].ch[1])t[t[i].ch[1]].val.update(t[i].lz),t[t[i].ch[1]].lz.update(t[i].lz);
		t[i].lz=data(0);
	}
}

inline void build(int &now,int l,int r,int D)
{
	int mid=(l+r)>>1;
	nth_element(id+l,id+mid,id+r+1,D?cmp1:cmp0);now=id[mid];
	if(l<mid)build(t[now].ch[0],l,mid-1,D^1);
	if(mid<r)build(t[now].ch[1],mid+1,r,D^1);
	t[t[now].ch[0]].fa=t[t[now].ch[1]].fa=now;
	update(t[now]);
}
inline void update(int i,int num,int p)
{
	if(!i||p<t[i].mn[0]||p>t[i].mx[1])return;
	if(p>=t[i].mx[0]&&p<=t[i].mn[1]){t[i].val.update(data(num)),t[i].lz.update(data(num));return;}
	pushdown(i);
	if(p>=t[i].d[0]&&p<=t[i].d[1])t[i].val.update(data(num));
	update(t[i].ch[0],num,p),update(t[i].ch[1],num,p);
}
inline void pdpath(int x){if(t[x].fa)pdpath(t[x].fa);pushdown(x);}

int main()
{
	n=getint(),m=getint();
	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(a[i]=getint());
	for(int i=1;i<=m;i++)
	{
		op[i]=getint(),x[i]=getint(),y[i]=getint();
		if(op[i]==2)t[++N].d[0]=x[i],t[N].d[1]=y[i],t[N].val=data(sum[y[i]]-sum[x[i]-1]),id[N]=N;
	}
	build(rt,1,N,0);
	for(int i=1,k=0;i<=m;i++)
	{
		if(op[i]&1)update(rt,y[i]-a[x[i]],x[i]),a[x[i]]=y[i];
		else pdpath(++k),printf("%lld\n",t[k].val.mn);
	}
}

技术图片

联考20200525 T1 数据结构

标签:using   void   printf   bool   ring   转化   标记   int()   str   

原文地址:https://www.cnblogs.com/Darknesses/p/12961052.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!