首页 > 代码库 > ●线段树题之wows
●线段树题之wows
●模拟考试的一道似乎是学长出的题,还不错,挺考代码能力的。以此记录。
●
(像手纸一样长的贴图……)
●题目大意:
有横向排布的n个点,每个点初始值都为0。
有m个操作(先输入操作类型com):
com==0:修改操作(接着输入l , r , a , k , p),解释见输入格式。(提供图帮助理解)。
com==1:查询操作(接着输入l , r),输出区间[ l , r ]内最长的等差数列的项数(要连续)。
●题解:
注意到是要找等差数列,即答案对应的区间个元素的差值应相等。即可以前后两元素的差值建线段树,然后维护区间最长的差值相等的一段。
(是不是思路很清晰,然而恶心的代码却搞了我大半个上午。)
●附上代码:
我上代码咯:(附上测试数据)
#include<cstdio> #include<cstring> #include<iostream> using namespace std; struct segment{ int l,r,nl,nr,mx,ml,mr,lazy; }t[400005]; int n,m; void pushdown(int u) { t[u*2].lazy+=t[u].lazy; t[u*2].nl+=t[u].lazy; t[u*2].nr+=t[u].lazy; t[u*2+1].lazy+=t[u].lazy; t[u*2+1].nl+=t[u].lazy; t[u*2+1].nr+=t[u].lazy; t[u].lazy=0; } void pushup(int u) { t[u].mx=max(t[u*2].mx,t[u*2+1].mx); t[u].ml=t[u*2].ml; t[u].mr=t[u*2+1].mr; t[u].nl=t[u*2].nl; t[u].nr=t[u*2+1].nr; if(t[u*2].nr==t[u*2+1].nl) { t[u].mx=max(t[u].mx,t[u*2].mr+t[u*2+1].ml); if(t[u*2].ml==(t[u*2].r-t[u*2].l+1)) t[u].ml+=t[u*2+1].ml; if(t[u*2+1].mr==(t[u*2+1].r-t[u*2+1].l+1)) t[u].mr+=t[u*2].mr; } } void build(int u,int l,int r) { t[u]=(segment){l,r,0,0,r-l+1,r-l+1,r-l+1}; if(l==r) return; int mid=(l+r)/2; build(u*2,l,mid); build(u*2+1,mid+1,r); } void add(int u,int l,int r,int x) { if(l<=t[u].l&&t[u].r<=r) { t[u].nl+=x; t[u].nr+=x; t[u].lazy+=x; return; } if(t[u].lazy) pushdown(u); int mid=(t[u].l+t[u].r)/2; if(l<=mid) add(u*2,l,r,x); if(mid<r) add(u*2+1,l,r,x); pushup(u); } void query(int u,int l,int r,int &mx,int &lm,int &rm,int &ln,int &rn) { int lmx=0,lml,lmr,lnl,lnr,rmx=0,rml,rmr,rnl,rnr; if(t[u].l==l&&t[u].r==r) { mx=t[u].mx; lm=t[u].ml; rm=t[u].mr; ln=t[u].nl; rn=t[u].nr; return; } if(t[u].lazy) pushdown(u); int mid=(t[u].l+t[u].r)/2; if(l<=mid) query(u*2,l,min(mid,r),lmx,lml,lmr,lnl,lnr); if(mid<r) query(u*2+1,max(mid+1,l),r,rmx,rml,rmr,rnl,rnr); if(lmx*rmx!=0) { mx=max(lmx,rmx); ln=lnl; rn=rnr; lm=lml; rm=rmr; if(lnr==rnl) { mx=max(mx,lmr+rml); if(lml==mid-l+1) lm+=rml; if(rmr==r-(mid+1)+1) rm+=lmr; } } else { if(lmx==0) swap(lmx,rmx),swap(lml,rml),swap(lmr,rmr),swap(lnl,rnl),swap(lnr,rnr); mx=lmx; lm=lml; rm=lmr; ln=lnl; rn=lnr; } } int main() { freopen("wows.in","r",stdin); freopen("wows.out","w",stdout); scanf("%d%d",&n,&m);n--; build(1,1,n); int com; for(int i=1,l,r,a,k,p;i<=m;i++) { scanf("%d",&com); if(com==0) { scanf("%d%d%d%d%d",&l,&r,&a,&k,&p); if(l>1) add(1,l-1,l-1,a); if(p-1>=l) add(1,l,p-1,k); if(r-1>=p) add(1,p,r-1,-k); if(r<n) add(1,r,r,-(a+(2*p-l-r)*k)); } if(com==1) { int ans,a1,a2,a3,a4; scanf("%d%d",&l,&r); r--; query(1,l,r,ans,a1,a2,a3,a4); printf("%d\n",ans+1); } } return 0; }
●线段树题之wows
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。