DAY 4 总结

T1

 

  • T4: 带权中位数问题:
  • 问题模型:节点到数轴上某一点的距离之和最短
  • 结论:中位数或者带权中位数的点
  • 证明:左右逼近,左边人数大于右边显然不能继续往左,那么这辆左右两边人数尽量相等的时候最优
  • https://www.cnblogs.com/chenhuanfa/archive/2012/11/20/2779453.html
  • https://www.cnblogs.com/oijzh/articles/2647134.html
  • https://blog.csdn.net/clover_hxy/article/details/50618736
  • 一共用四课线段树来维护
  • 然后注意,和某个位置的权值差值我们可以维护下表标号来减去权值来进行求解就可以了
  • 代码:
  • #include <stdio.h>
    #include <algorithm>
    #include <cstring>
    #define lson (k<<1)
    #define rson (k<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
    int n,q;
    int a[maxn];
    ll sum;
    
    
    struct seg1
    {
        ll tr[maxn*12];
        void push(int k)
        {
            tr[k]=tr[lson]+tr[rson];
        }
        void build(int k,int l,int r)
        {
            //printf("%d \n",k);
            if(l==r)
            {
                tr[k]=a[l];
                return;
            }
            build(lson,l,mid);
            build(rson,mid+1,r);
            push(k);
        }
        void modify(int k,int l,int r,int pos,int v)
        {
            if(l==r&&l==pos)
            {
                tr[k]+=v;
                return;
            }
            if(pos<=mid) modify(lson,l,mid,pos,v);
            else modify(rson,mid+1,r,pos,v);
            push(k);
        }
        int qry(int k,int l,int r,ll val)
        {
            if(l==r) return l;
            if(tr[lson]<val) return qry(rson,mid+1,r,val-tr[lson]);
            else return qry(lson,l,mid,val);
        }
    }t1;
    struct seg2
    {
        ll tr[maxn*12],tag[maxn*12];
        void push(int k)
        {
            tr[k]=tr[lson]|tr[rson];
        }
        void build(int k,int l,int r)
        {
            if(l==r)
            {
                tr[k]=1;
                return;
            }
            build(lson,l,mid);
            build(rson,mid+1,r);
            push(k);
        }
        void pushdown(int k)
        {
            if(!tag[k]) return;
            tag[lson]=tag[rson]=tag[k];
            tr[lson]=tr[rson]=tag[k]-1;
            tag[k]=0;
        }
        void modify(int k,int l,int r,int x,int y,int v)
        {
            if(l>=x&&r<=y)
            {
                tr[k]=v;
                tag[k]=v+1;
                return;
            }
            pushdown(k);
            if(x<=mid) modify(lson,l,mid,x,y,v);
            if(mid<y) modify(rson,mid+1,r,x,y,v);
            push(k);
        }
        int ql(int k,int l,int r,int pos)
        {
            if(l>pos||!tr[k]) return -1;//注意是完全排除,而非大于等于 
            if(l==r) return l;
            pushdown(k);//每次询问之前都要pushdown!!! 
            if(r<=pos)
            {
                if(tr[rson]) return ql(rson,mid+1,r,pos);
                else return ql(lson,l,mid,pos);
            }
            int v=ql(rson,mid+1,r,pos);
            if(v!=-1) return v;
            else return ql(lson,l,mid,pos);
        }
        int qr(int k,int l,int r,int pos)
        {
            if(r<pos||!tr[k]) return -1;
            if(l==r) return l;
            pushdown(k);
            if(l>=pos)
            {
                if(tr[lson]) return qr(lson,l,mid,pos);
                else return qr(rson,mid+1,r,pos);
            }
            int v=qr(lson,l,mid,pos);
            if(v!=-1) return v;
            else return qr(rson,mid+1,r,pos);
        } 
    }t2;
    struct bit
    {
        ll tr[maxn<<2];
        void add(int x,ll v)
        {
            //printf("%d %d\n",x,v);
            for(int i=x;i<=n;i+=(-i)&i)
            {
                tr[i]+=v;
            }
            return;
        }
        ll  qry(int x)
        {
            ll res=0;
            for(int i=x;i;i-=(-i)&i)
            {
                res+=tr[i];
                //printf("%d %d\n",x,res);
            }
            //printf("%d\n",res);
            return res;
        }
    }t3,t4;
    ll clac2(int pos)
    {
        ll a=t3.qry(pos),b=sum-a,sa=t4.qry(pos),sb=t4.qry(n)-sa;
        return (a-b)*pos-sa+sb;
    }
    int clac()
    {
        int q=t1.qry(1,1,n,(sum-1)/2+1);
        int lp=t2.ql(1,1,n,q);
        ll ans=-1;
        if(lp!=-1) ans=clac2(lp);
        if(lp==q) return lp;
        int rp=t2.qr(1,1,n,q);
        if(rp!=-1)
        {
            if(ans==-1) return rp;
            else if(ans<=clac2(rp)) return lp;
            else return rp;
        }
        if(ans!=-1) return lp;
        return -1;
    }
    int main()
    {
    //    freopen("position.in", "r", stdin); freopen("position.out", "w", stdout);
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);sum+=a[i];
            t3.add(i,(1ll)*a[i]);
            t4.add(i,(1ll)*i*a[i]);
            t1.modify(1,1,n,i,a[i]);
        } 
        printf("%lld %d\n",t3.qry(3),t4.qry(4));
        //printf("%d\n",t1.qry(1,1,n,5));
        t1.build(1,1,n);
        t2.build(1,1,n);
        while(q--)
        {
            int mod,x,y;
            scanf("%d%d%d",&mod,&x,&y);
            if(mod==1)
            {
                sum+=y;
                t3.add(x,y);
                t4.add(x,1ll*x*y);
                t1.modify(1,1,n,x,y);        
            }
            if(mod==2)
            {
                sum-=y;
                t3.add(x,-y);
                t4.add(x,-1ll*x*y);
                t1.modify(1,1,n,x,-y);
            }
            if(mod==3) t2.modify(1,1,n,x,y,1);
            if(mod==4) t2.modify(1,1,n,x,y,0);
            printf("%d\n",clac());
        }
        return 0;
    } 

     

posted @ 2020-11-04 10:16  ILH  阅读(105)  评论(0)    收藏  举报