1. 程式人生 > >HDU - 6315 Naive Operations (線段樹+思維) 2018 Multi-University Training Contest 2

HDU - 6315 Naive Operations (線段樹+思維) 2018 Multi-University Training Contest 2

延遲 給定 要求 lse define 位置 efi operation date

題意:數量為N的序列a和b,a初始全為0,b為給定的1-N的排列。有兩種操作:1.將a序列區間[L,R]中的數全部+1;2.查詢區間[L,R]中的 ?ai/bi?(向下取整)

分析:對於一個位置i,如果ai<bi,那麽該位置不能對結果做出貢獻;而當某一次操作後,ai>=bi了,就對結果的貢獻值+1。那麽可以用在線段樹的結點中維護每個區間的最大a和最小b,和已經產生的貢獻cnt。如果一個區間中最大的a超過了b,那麽就說明此次更新操作使該區間的結果產生了變化,那麽就要向下找到那個產生貢獻的位置。當更新完結果值以後,就將這個位置上的bi再加上bi(由於結果要求向下取整),那麽相當於這個位置的ai又要重新更新bi次才能再次產生貢獻。

所以,update函數中,如果出現a>=b的情況,那麽我們必須遞歸到最底層找到出現;如果a<b,那麽只要打上延遲標記即可。

#include<bits/stdc++.h>
#define Lson rt<<1,l,m
#define Rson rt<<1|1,m+1,r
using namespace std;
typedef long long LL;
const int maxn =1e5+5;
struct Node{
    int cnt,addv,maxa,minb;
}tree[maxn<<2];
int b[maxn];
void pushup(int rt) { tree[rt].cnt = tree[rt<<1].cnt+tree[rt<<1|1].cnt; tree[rt].maxa = max(tree[rt<<1].maxa,tree[rt<<1|1].maxa); tree[rt].minb = min(tree[rt<<1].minb,tree[rt<<1|1].minb); } void pushdown(int rt) { if(tree[rt].addv){ int v=tree[rt].addv; tree[rt].addv
=0; tree[rt<<1].maxa+=v; tree[rt<<1|1].maxa+=v; tree[rt<<1].addv+=v; tree[rt<<1|1].addv+=v; } } void build(int rt,int l,int r) { tree[rt].addv=0; if(l==r){ tree[rt].cnt = tree[rt].maxa = 0; tree[rt].minb = b[l]; return; } int m = (l+r)>>1; build(Lson); build(Rson); pushup(rt); } void update(int rt,int l,int r,int L,int R) { if(L<=l && R>=r){ tree[rt].maxa++; if(tree[rt].maxa<tree[rt].minb){ //還沒有元素做出貢獻 tree[rt].addv++; return; } else if(l==r){ tree[rt].cnt++; tree[rt].minb+=b[l]; return; } } pushdown(rt); int m = (l+r)>>1; if(L<=m)update(Lson,L,R); if(R>m)update(Rson,L,R); pushup(rt); } int query(int rt,int l,int r,int L,int R) { if(L<=l&&R>=r) return tree[rt].cnt; int m =(l+r)>>1; pushdown(rt); int ans=0; if(L<=m) ans+=query(Lson,L,R); if(R>m) ans+=query(Rson,L,R); return ans; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int T,N,M,u,v,tmp; while(scanf("%d%d",&N,&M)==2){ for(int i=1;i<=N;++i) scanf("%d",&b[i]); build(1,1,N); char op[8]; int L,R; while(M--){ scanf("%s %d %d",op,&L,&R); if(op[0]==a) update(1,1,N,L,R); else printf("%d\n",query(1,1,N,L,R)); } } return 0; }

HDU - 6315 Naive Operations (線段樹+思維) 2018 Multi-University Training Contest 2