bzoj 1091 Zju2112 Dynamic Rankings - 整体二分 - 学习笔记

64 篇文章 0 订阅
2 篇文章 0 订阅

整体二分·屯板子

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<assert.h>
#define N 110000
#define lb(x) (x&-x)
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
struct BIT{
    int v[N],n,c,sx[N],sv[N];
    inline int init(int _n)
    { n=_n,c=0;return 0; }
    inline int update(int x,int val)
    {
        c++,sx[c]=x,sv[c]=val;
        for(;x<=n;x+=lb(x)) v[x]+=val;
        return 0;
    }
    inline int query(int x,int y)
    {
        int ans=0;
        for(;y;y-=lb(y)) ans+=v[y];
        for(x--;x;x-=lb(x)) ans-=v[x];
        return ans;
    }
    inline int clear()
    {
        for(int i=c;i>=1;i--)
            update(sx[i],-sv[i]),c--;
        return c=0;
    }
}b;
struct P{
    int kind,x,y,v,ans;
    P(int _x=0,int _y=0,int _v=0)
    { x=_x,y=_y,v=_v,kind=0,ans=0; }
    inline P operator=(const P &p)
    { kind=p.kind,x=p.x,y=p.y,v=p.v,ans=p.ans;return *this; }
}p[N],tmpL[N],tmpR[N];
int v[N],a[N],c,pc,qc,ans[N];char opt[10];
int solve(int L,int R,int s,int t)
{
    if(L>R) return 0;int mid=(s+t)>>1;
    if(s==t)
    {
        for(int i=L;i<=R;i++)
            if(p[i].kind) p[i].ans=mid;
        return 0;
    }
    int Lc=0,Rc=0,c=L-1;
//  debug(L)sp,debug(R)sp,debug(s)sp,debug(t)ln;
    for(int i=L;i<=R;i++)
        if(p[i].kind)//1:query
        {
            int s=b.query(p[i].x,p[i].y);
//          debug(i)sp,debug(p[i].x)sp,debug(p[i].y)sp,debug(p[i].v)sp,debug(s)ln;
            if(p[i].v<=s) tmpL[++Lc]=p[i];
            else p[i].v-=s,tmpR[++Rc]=p[i];
        }
        else{
//          debug(i)sp,debug(p[i].x)sp,debug(p[i].y)sp,debug(p[i].v)ln;
            if(p[i].y>mid) tmpR[++Rc]=p[i];
            else b.update(p[i].x,p[i].v),tmpL[++Lc]=p[i];
        }
//  cerr ln;
    for(int i=1;i<=Lc;i++) p[++c]=tmpL[i];
    for(int i=1;i<=Rc;i++) p[++c]=tmpR[i];
    b.clear(),solve(L,L+Lc-1,s,mid),solve(L+Lc,R,mid+1,t);
    return 0;
}
int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),v[++c]=a[i],p[++pc]=P(i,a[i],1);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",opt);int x,y;
        if(opt[0]=='Q') p[++pc].kind=++qc,scanf("%d%d%d",&p[pc].x,&p[pc].y,&p[pc].v);
        else scanf("%d%d",&x,&y),p[++pc]=P(x,a[x],-1),p[++pc]=P(x,a[x]=y,1),v[++c]=y;
    }
    sort(v+1,v+c+1),c=unique(v+1,v+c+1)-v-1;
    for(int i=1;i<=pc;i++)
        if(!p[i].kind) p[i].y=lower_bound(v+1,v+c+1,p[i].y)-v;
//  for(int i=1;i<=pc;i++) debug(i)sp,debug(p[i].kind)sp,debug(p[i].x)sp,debug(p[i].y)sp,debug(p[i].v)ln;
    b.init(c),solve(1,pc,1,c);
    for(int i=1;i<=pc;i++)
        if(p[i].kind) ans[p[i].kind]=v[p[i].ans];
    for(int i=1;i<=qc;i++) printf("%d\n",ans[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值