根据一个数六次√必死,我们可以打标记死了就不管他了,于是有贡献的操作复杂度为O(n*logn*6),然而我们还有由于盲目修改造成的多余代价我们把每次查询的区间分成三部分前全死,中残,后全死,对于中残,我们的操作都是由于为了有价值的操作而操作的,(无论中间残的那里面断断续续的死的是多长,他的向下都是为了做出贡献),而两边的多余费用最多O(4*logn),最终约为O(10*n*logn)
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #define MAXN 100005 using namespace std; typedef long long LL; inline LL read_LL() { LL sum=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9') { sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar(); } return sum; } inline int read() { int sum=0; char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9') { sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar(); } return sum; } struct Seg_Tree { Seg_Tree *ch[2]; int over,l,r,mid; LL sum; }S[MAXN<<2],*root; LL key[MAXN]; int n,m; int sz; inline Seg_Tree *New(int l,int r) { Seg_Tree *p=S+sz; sz++; p->l=l; p->r=r; p->mid=(l+r)>>1; return p; } inline void pushup(Seg_Tree *p) { if(p->l==p->r) { p->sum=key[p->mid]; if(p->sum==1) p->over=1; return; } p->sum=p->ch[0]->sum+p->ch[1]->sum; if(p->ch[0]->over&&p->ch[1]->over) p->over=1; } void build(Seg_Tree *p) { if(p->l==p->r) { pushup(p); return; } p->ch[0]=New(p->l,p->mid); build(p->ch[0]); p->ch[1]=New(p->mid+1,p->r); build(p->ch[1]); pushup(p); } inline void Init() { n=read(); for(int i=1;i<=n;i++) key[i]=read_LL(); root=New(1,n); build(root); } void pushdown(Seg_Tree *p,int l,int r) { if(p->over)return; if(p->l==p->r) { key[p->mid]=(LL)(sqrt(key[p->mid]+0.5)); pushup(p); return; } if(p->mid>=l) pushdown(p->ch[0],l,r); if(p->mid<r) pushdown(p->ch[1],l,r); pushup(p); } LL query(Seg_Tree *p,int l,int r) { if(l<=p->l&&p->r<=r) return p->sum; LL ans=0; if(l<=p->mid) ans+=query(p->ch[0],l,r); if(p->mid<r) ans+=query(p->ch[1],l,r); return ans; } inline void work() { m=read(); while(m--) { int opt=read(),x=read(),y=read(); if(x>y)x^=y^=x^=y; if(opt) printf("%lld ",query(root,x,y)); else pushdown(root,x,y); } } int main() { freopen("god.in","r",stdin); freopen("god.out","w",stdout); Init(); work(); return 0; }