博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
uoj#228. 基础数据结构练习题(线段树)
阅读量:5972 次
发布时间:2019-06-19

本文共 2873 字,大约阅读时间需要 9 分钟。

只有区间加区间开方我都会……然而加在一起我就gg了……

然后这题的做法就是对于区间加直接打标记,对于区间开方,如果这个区间的最大值等于最小值就直接区间覆盖(据ljh_2000大佬说这个区间覆盖可以改成区间减去一个数),否则的话如果最小值等于最大值加一,且最小值和最大值开方之后减少的值一样,也直接打上区间减标记,否则递归下去

考虑复杂度,如果两个相邻的点导致包含这两个点的区间必须从这里分开才能进行开根操作,那么就称其为一个分界点,一个分界点相当于把区间开根分成两次。因为序列的初始值小于等于\(10^5\),最多开根\(4\)次分界点就会消失,而区间加的权值也小于等于\(10^5\),最多增加两个点\(4\)次开根,常数而已

然后试了试ljh_2000大佬说的标记永久化+不下传……跑得贼快啊……

//minamoto#include
#define R register#define ll long long#define ls (p<<1)#define rs (p<<1|1)#define fp(i,a,b) for(R int i=a,I=b+1;i
I;--i)#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)inline ll max(const R ll &x,const R ll &y){return x>y?x:y;}inline ll min(const R ll &x,const R ll &y){return x
'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f;}char sr[1<<21],z[20];int C=-1,Z=0;inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}void print(R ll x){ if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++C]=z[Z],--Z);sr[++C]='\n';}const int N=1e5+5;struct node{int len;ll sum,tag,mn,mx;}tr[N<<2];int n,m,a[N],ql,qr,val,op;ll ans;inline void pd(R node &x,R ll v){x.tag+=v,x.mn+=v,x.mx+=v,x.sum+=v*x.len;}void upd(R int p){ tr[p].sum=tr[ls].sum+tr[rs].sum+tr[p].tag*tr[p].len; tr[p].mx=max(tr[ls].mx,tr[rs].mx)+tr[p].tag; tr[p].mn=min(tr[ls].mn,tr[rs].mn)+tr[p].tag;}void build(int p,int l,int r){ tr[p].len=r-l+1; if(l==r)return (void)(tr[p].sum=tr[p].mx=tr[p].mn=a[l]); int mid=(l+r)>>1; build(ls,l,mid),build(rs,mid+1,r); upd(p);}void update(int p,int l,int r){ if(ql<=l&&qr>=r)return pd(tr[p],val); int mid=(l+r)>>1; if(ql<=mid)update(ls,l,mid); if(qr>mid)update(rs,mid+1,r); upd(p);}void Sqrt(int p,int l,int r,ll tag){ if(ql<=l&&qr>=r){ if(tr[p].mx==tr[p].mn){ ll del=tr[p].mn+tag-(ll)sqrt(tr[p].mn+tag); return pd(tr[p],-del); } ll c1=sqrt(tr[p].mn+tag)+1,c2=sqrt(tr[p].mx+tag); if(tr[p].mx==tr[p].mn+1&&c1==c2){ ll del=tr[p].mn+tag-(ll)sqrt(tr[p].mn+tag); return pd(tr[p],-del); } } int mid=(l+r)>>1; if(ql<=mid)Sqrt(ls,l,mid,tag+tr[p].tag); if(qr>mid)Sqrt(rs,mid+1,r,tag+tr[p].tag); upd(p);}void query(int p,int l,int r,ll tag){ if(ql<=l&&qr>=r)return (void)(ans+=tr[p].sum+tr[p].len*tag); int mid=(l+r)>>1; if(ql<=mid)query(ls,l,mid,tag+tr[p].tag); if(qr>mid)query(rs,mid+1,r,tag+tr[p].tag);}int main(){// freopen("testdata.in","r",stdin); n=read(),m=read(); fp(i,1,n)a[i]=read(); build(1,1,n); while(m--){ op=read(),ql=read(),qr=read(); switch(op){ case 1:val=read(),update(1,1,n);break; case 2:Sqrt(1,1,n,0);break; case 3:ans=0;query(1,1,n,0);print(ans);break; } }return Ot(),0;}

转载于:https://www.cnblogs.com/bztMinamoto/p/10249249.html

你可能感兴趣的文章
初遇 Asp.net MVC 数据库依赖缓存那些事儿
查看>>
SQL Server遗失管理权限账号密码怎么办?
查看>>
C#处理Exception的常用方法总结
查看>>
写文件的工具类,输出有格式的文件(txt、json/csv)
查看>>
自定义spring参数注解 - 打破@RequestBody单体限制
查看>>
Hadoop生态圈-Hive的自定义函数之UDF(User-Defined-Function)
查看>>
MongoDB基础入门
查看>>
ASP.NET Core 2 学习笔记(三)中间件
查看>>
SpringMVC Controller介绍及常用注解
查看>>
056 Java搭建kafka环境
查看>>
Linux Namespace : Network
查看>>
sklearn word2vec 实践
查看>>
Go中string转[]byte的陷阱
查看>>
Android 自定义AlertDialog的写法和弹出软键盘和覆盖状态栏
查看>>
SpringBoot------自定义拦截器
查看>>
Python | 一行命令生成动态二维码
查看>>
django学习--1
查看>>
即将上线的Hive服务器面临的一系列填坑笔记
查看>>
转:Mosquitto用户认证配置
查看>>
SpringBoot上传文件到本服务器 目录与jar包同级
查看>>