HDU - 5828 Rikka with Sequence (线段树)

题目链接

三种操作:区间加,区间开根号,区间求和。

修改的时候判断区间内的最大值和最小值是否相等或者差1,如果相等则变为区间赋值,否则再判断开根号之后的最大值和最小值是否相等,如果相等则区间赋值,否则区间加法。

这题的数据也忒恶心了点吧?本来直接判断相等就能解决的问题,非要加上一个玄学的优化才能过掉...

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N=1e5+10,inf=0x3f3f3f3f;
 5 int n,m,a[N];
 6 ll sum[N<<2],mx[N<<2],mi[N<<2],ad[N<<2],st[N<<2];
 7 #define ls (u<<1)
 8 #define rs (u<<1|1)
 9 #define mid ((l+r)>>1)
10 void add(int u,ll x,int l,int r) {sum[u]+=x*(r-l+1),mx[u]+=x,mi[u]+=x,ad[u]+=x;}
11 void Set(int u,ll x,int l,int r) {sum[u]=x*(r-l+1),mx[u]=mi[u]=x,ad[u]=0,st[u]=x;}
12 void pu(int u) {sum[u]=sum[ls]+sum[rs],mx[u]=max(mx[ls],mx[rs]),mi[u]=min(mi[ls],mi[rs]);}
13 void pd(int u,int l,int r) {
14     if(~st[u])Set(ls,st[u],l,mid),Set(rs,st[u],mid+1,r),st[u]=-1;
15     if(ad[u])add(ls,ad[u],l,mid),add(rs,ad[u],mid+1,r),ad[u]=0;
16 }
17 void build(int u=1,int l=1,int r=n) {
18     ad[u]=0,st[u]=-1;
19     if(l==r) {sum[u]=mx[u]=mi[u]=a[l]; return;}
20     build(ls,l,mid),build(rs,mid+1,r),pu(u);
21 }
22 void upd1(int L,int R,ll x,int u=1,int l=1,int r=n) {
23     if(l>=L&&r<=R) {add(u,x,l,r); return;}
24     if(l>R||r<L)return;
25     pd(u,l,r),upd1(L,R,x,ls,l,mid),upd1(L,R,x,rs,mid+1,r),pu(u);
26 }
27 void upd2(int L,int R,int u=1,int l=1,int r=n) {
28     if(l>=L&&r<=R&&mx[u]-mi[u]<=1) {
29         if((ll)sqrt(mx[u]+0.5)==(ll)sqrt(mi[u]+0.5))Set(u,(ll)sqrt(mx[u]+0.5),l,r);
30         else add(u,(ll)sqrt(mx[u]+0.5)-mx[u],l,r);
31         return;
32     }
33     if(l>R||r<L)return;
34     pd(u,l,r),upd2(L,R,ls,l,mid),upd2(L,R,rs,mid+1,r),pu(u);
35 }
36 ll qry(int L,int R,int u=1,int l=1,int r=n) {
37     if(l>=L&&r<=R)return sum[u];
38     if(l>R||r<L)return 0;
39     pd(u,l,r);
40     return qry(L,R,ls,l,mid)+qry(L,R,rs,mid+1,r);
41 }
42 int main() {
43     int T;
44     for(scanf("%d",&T); T--;) {
45         scanf("%d%d",&n,&m);
46         for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
47         build();
48         while(m--) {
49             int f,l,r,x;
50             scanf("%d%d%d",&f,&l,&r);
51             if(f==1)scanf("%d",&x);
52             if(f==1)upd1(l,r,x);
53             else if(f==2)upd2(l,r);
54             else if(f==3)printf("%lld\n",qry(l,r));
55         }
56     }
57     return 0;
58 }

 

posted @ 2019-06-28 14:30  jrltx  阅读(255)  评论(0编辑  收藏  举报