Naive Operations HDU - 6315
阿新 • • 發佈:2018-10-31
題意是給一個長度為n的a,b陣列,然後有2種操作,一種是a陣列l~r區間+1,第二種是查詢l~r區間ai/bi之和。維護區間內最大的a值和最小的b值,對一段區間進行成段更新後,如果maxa==minb說明往該節點的兒子節點更新可能會對該區間之和產生貢獻,那就更新下去,往下面更新時若找到了maxa==minb的葉子節點,則該葉子節點的minb加上其初始的值(b[l]),且區間和++,比如說2/2,將分母即該節點的minb+b[l],區間之和加1.若maxa<minb的話說明往該節點的兒子節點更新不可能會對該區間之和產生貢獻,因此不必更新下去了,在當前節點打個標記即可,查詢的話就和普通線段樹查詢一樣。
#include<bits/stdc++.h> using namespace std; const int maxn=1e5; #define ll long long #define ls 2*rt #define rs 2*rt+1 struct node { ll sum; int l,r,lazy,maxa,minb; bool tag; }tree[4*maxn]; int b[maxn+10]; inline void pushup(int rt) { tree[rt].sum=tree[ls].sum+tree[rs].sum; tree[rt].maxa=max(tree[ls].maxa,tree[rs].maxa); tree[rt].minb=min(tree[ls].minb,tree[rs].minb); } inline void pushdown(int rt) { if(tree[rt].tag) { tree[ls].maxa+=tree[rt].lazy; tree[rs].maxa+=tree[rt].lazy; tree[ls].tag=true; tree[ls].lazy+=tree[rt].lazy; tree[rs].tag=true; tree[rs].lazy+=tree[rt].lazy; tree[rt].tag=false; tree[rt].lazy=0; } } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; tree[rt].tag=false; tree[rt].lazy=0; if(l==r) { tree[rt].maxa=0; tree[rt].minb=b[l]; tree[rt].sum=0; return ; } int mid=(l+r)>>1; build(l,mid,ls); build(mid+1,r,rs); pushup(rt); } void update(int l,int r,int rt) { if(tree[rt].l>=l&&tree[rt].r<=r) { tree[rt].maxa++; if(tree[rt].maxa<tree[rt].minb)///滿足該條件則對rt節點對應區間更新不可能對區間和有貢獻,當然ls,rs也是一樣不會有貢獻的,因此不必更新到rt對應區間的每個葉子節點 { tree[rt].tag=true; tree[rt].lazy++; return ; } else if(tree[rt].l==tree[rt].r)///滿足該條件說明這個rt節點對應區間的maxa==minb,說明更新該節點是對區間和有貢獻的,且rt節點是葉子節點 { tree[rt].sum++; tree[rt].minb+=b[tree[rt].l]; return ; } } ///執行下面的語句的話,說明rt節點不能成段更新或rt節點能成段更新,更新該節點對應的區間可能對區間和有貢獻。這2種情況都需要更新到rt的兒子 pushdown(rt); int mid=(tree[rt].l+tree[rt].r)/2; if(mid>=r) update(l,r,ls); else if(mid+1<=l) update(l,r,rs); else { update(l,r,ls); update(l,r,rs); } pushup(rt); } ll query(int l,int r,int rt) { if(tree[rt].l>=l&&tree[rt].r<=r) { return tree[rt].sum; } ll ans=0; int mid=(tree[rt].l+tree[rt].r)>>1; if(mid>=r) ans=query(l,r,ls); else if(mid+1<=l) ans=query(l,r,rs); else { ans=query(l,r,ls); ans+=query(l,r,rs); } return ans; } int main() { int n,q; while(scanf("%d %d",&n,&q)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&(b[i])); build(1,n,1); char op[10]; int l,r; while(q--) { scanf("%s %d %d",op,&l,&r); if(op[0]=='a') update(l,r,1); else printf("%lld\n",query(l,r,1)); } } return 0; }