【线段树】[CodeForces - 717F]Heroes of Making Magic III

来源:互联网 发布:淘宝店铺自定义装修 编辑:程序博客网 时间:2024/06/05 04:39

题目大意

一个长度为n的序列,每一个位置都有一些小怪。英雄可以在序列上左右移动,并且可以击杀一个他所到达的位置上的小怪,每次移动必须击杀小怪。
有两种操作:

  • 1 a b k 区间[a,b]中的每一个位置都增加k个小怪
  • 2 a b 英雄能否在一个端点开始,在另一个端点结束,并且杀光[a,b]内所有小怪,英雄不能移动出区间。

分析

设第i个位置有ai个小怪
假设区间为[l,r],我们让英雄从左端点开始,向右移动。假设英雄当前在i,我们让英雄在i,i+1之间徘徊,直到把第i个位置的小怪都杀光。
如果英雄从右端点开始,实际上就是把从左端点开始的移动反过来。

考虑这种情况我们需要哪些条件:
al1
al+1al0
al+1(al+1al+1)0al+1al+1+al>=1

al+ial+i1+al+i2[imod2=0]
arar1+ar2[rl+1mod2=0]

考虑一下怎么维护,
diaiai1+ai2,那么di+1=ai+1di

假设当前询问的区间是[l,r]
那么,设di=(ai+lai+l1+ai+l2)

di={di+dl1di+dl1i is eveni is odd

在做修改操作的时候
[l,r]区间内,和l奇偶性相同的位置的d+k
区间后,如果区间长度是偶数,就没有影响,否则,和l奇偶性相同的+k,不同的k

我们用可以对奇偶位置分别维护。

代码

#include<cstdio>#include<algorithm>#define MAXN 200000#define INF 0x7fffffffusing namespace std;void Read(int &x){    char c;    while(c=getchar(),c!=EOF)        if(c>='0'&&c<='9'){            x=c-'0';            while(c=getchar(),c>='0'&&c<='9')                x=x*10+c-'0';            ungetc(c,stdin);            return;        }}int n,a[MAXN+10],d[MAXN+10],m;struct node{    int odd,even,mio,mie;}tree[(1<<18)+10];inline void update(int i){    tree[i].mio=min(tree[i<<1].mio,tree[(i<<1)|1].mio);    tree[i].mie=min(tree[i<<1].mie,tree[(i<<1)|1].mie);}void build(int i,int l,int r){    if(l==r){        tree[i].mio=d[(l<<1)-1];        tree[i].mie=d[l<<1];        return;    }    tree[i].odd=tree[i].even=0;    int mid((l+r)>>1);    build(i<<1,l,mid);    build((i<<1)|1,mid+1,r);    update(i);}void read(){    Read(n);    int i;    for(i=1;i<=n;i++){        Read(a[i]);        d[i]=a[i]-d[i-1];    }    build(1,1,(n+1)>>1);}inline void push_down(int i){    if(tree[i].even){        tree[i<<1].even+=tree[i].even;        tree[(i<<1)|1].even+=tree[i].even;        tree[i<<1].mie+=tree[i].even;        tree[(i<<1)|1].mie+=tree[i].even;        tree[i].even=0;    }    if(tree[i].odd){        tree[i<<1].odd+=tree[i].odd;        tree[(i<<1)|1].odd+=tree[i].odd;        tree[i<<1].mio+=tree[i].odd;        tree[(i<<1)|1].mio+=tree[i].odd;        tree[i].odd=0;    }}void insert(int i,int l,int r,int ll,int rr,int od,int ev){    if(ll<=l&&r<=rr){        tree[i].even+=ev;        tree[i].odd+=od;        tree[i].mie+=ev;        tree[i].mio+=od;        return;    }    if(ll>r||rr<l)        return;    int mid((l+r)>>1);    push_down(i);    insert(i<<1,l,mid,ll,rr,od,ev);    insert((i<<1)|1,mid+1,r,ll,rr,od,ev);    update(i);}int get_mi_e(int i,int l,int r,int ll,int rr){    if(ll<=l&&r<=rr)        return tree[i].mie;    if(ll>r||rr<l)        return INF;    int mid((l+r)>>1);    push_down(i);    return min(get_mi_e(i<<1,l,mid,ll,rr),get_mi_e((i<<1)|1,mid+1,r,ll,rr));}int get_mi_o(int i,int l,int r,int ll,int rr){    if(ll<=l&&r<=rr)        return tree[i].mio;    if(ll>r||rr<l)        return INF;    int mid((l+r)>>1);    push_down(i);    return min(get_mi_o(i<<1,l,mid,ll,rr),get_mi_o((i<<1)|1,mid+1,r,ll,rr));}void solve(){    int p,l,r,v,pre;    Read(m);    while(m--){        Read(p),Read(l),Read(r);        l++,r++;        if(p==1){            Read(v);            if(l&1)                insert(1,1,(n+1)>>1,(l+1)>>1,(r+1)>>1,v,0);            else                insert(1,1,(n+1)>>1,l>>1,r>>1,0,v);            if(!((r-l)&1)){                if(r&1){                    insert(1,1,(n+1)>>1,(r>>1)+1,(n+1)>>1,0,-v);                    insert(1,1,(n+1)>>1,(r>>1)+2,(n+1)>>1,v,0);                }                else                    insert(1,1,(n+1)>>1,(r>>1)+1,(n+1)>>1,-v,v);            }        }        else{            if(l&1){                if(l==1)                    pre=0;                else                    pre=get_mi_e(1,1,(n+1)>>1,l>>1,l>>1);                if(r&1){                    if(get_mi_o(1,1,(n+1)>>1,(r+1)>>1,(r+1)>>1)+pre!=1){                        puts("0");                        continue;                    }                }                else                    if(get_mi_e(1,1,(n+1)>>1,r>>1,r>>1)-pre){                        puts("0");                        continue;                    }                if(get_mi_o(1,1,(n+1)>>1,(l>>1)+1,(r+1)>>1)>=1-pre&&get_mi_e(1,1,(n+1)>>1,(l+1)>>1,r>>1)>=pre)                    puts("1");                else                    puts("0");            }            else{                if(l==1)                    pre=0;                else                    pre=get_mi_o(1,1,(n+1)>>1,l>>1,l>>1);                if(r&1){                    if(get_mi_o(1,1,(n+1)>>1,(r+1)>>1,(r+1)>>1)-pre){                        puts("0");                        continue;                    }                }                else                    if(get_mi_e(1,1,(n+1)>>1,r>>1,r>>1)+pre!=1){                        puts("0");                        continue;                    }                pre=get_mi_o(1,1,(n+1)>>1,l>>1,l>>1);                if(get_mi_o(1,1,(n+1)>>1,(l>>1)+1,(r+1)>>1)>=pre&&get_mi_e(1,1,(n+1)>>1,(l+1)>>1,r>>1)>=1-pre)                    puts("1");                else                    puts("0");            }        }    }}int main(){    read();    solve();}
0 0
原创粉丝点击