• HDU5412 CRB and Queries 整体二分


    传送门

    刚觉得最近写代码比较顺畅没什么Bug,cdq分治真是我的一个噩梦。。

    整体二分模板题,带修改的区间第k小。

    vjudge不知抽什么风,用不了,hdu忘了密码了一直在那里各种试,难受。。

    写得比较鬼畜。

    整体二分,传了三个l,r分别是二分答案的 el ,er ,对当前答案可能有贡献的修改区间的 l , r ,答案在当前二分区间中的询问区间 ql, qr

    每次对el, er 取个mid,然后修改区间是按时间排好序的,按时间扫过去,在修改值大于mid的地方+1(区间第k小等价于大于等于它的数有len-k+1个),同时把这些区间往右放,其余区间往作放。

    然后对于询问区间查询区间内1的个数,就知道了区间中大于等于mid的数的个数,如果个数大于等于len-k+1就把询问区间往右放,否则减去查询的值往左放。

    el==er时对所有的询问区间更新答案。

    注意的时我的这种鬼畜写法往右放时二分区间是mid,r,往左是l,mid-1,所以对于偶数长度的区间强制mid靠右才ok。。

    跑得还蛮快的。

    反正我觉得树套树优秀多了,虽然跑得慢一点。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<ctime>
    #include<cmath>
    const int N=300007;
    typedef long long LL;
    using namespace std;
    int n,m,cq,v[N],ans[N];
    
    template<typename T> void read(T &x) {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    struct node {
        int ti,pos,v,f;
        node(){}
        node(int ti,int pos,int v,int f):ti(ti),pos(pos),v(v),f(f){}
    }cg[N],tp[N];
    struct qs{
        int id,ti,l,r,k;
        qs(){}
        qs(int id,int ti,int l,int r,int k):id(id),ti(ti),l(l),r(r),k(k){}
    }q[N],t[N];
    
    int sum[N];
    void add(int x,int v) {
        for(int i=x;i<=n;i+=(i&(-i)))
            sum[i]+=v;
    }
    int qry(int x) {
        int res=0;
        for(int i=x;i;i-=(i&(-i)))
            res+=sum[i];
        return res;
    }
    
    void cdq(int el,int er,int l,int r,int ql,int qr) {
        if(el>er||ql>qr) return; 
        if(el==er) {
            for(int i=ql;i<=qr;i++) ans[q[i].id]=el;
            return;    
        }
        int mid=((el+er)>>1); if((el+er)&1) mid++;
        int ll=l-1,rr=r+1,lx=ql-1,rx=qr+1,now=ql;
        for(int i=l;i<=r+1;i++) {
            while(now<=qr&&(i==r+1||q[now].ti<cg[i].ti)) {
                int dd=qry(q[now].r)-qry(q[now].l-1);
                if(dd>=q[now].k) t[--rx]=q[now];
                else { q[now].k-=dd; t[++lx]=q[now]; }
                now++;
            } if(i==r+1) break;
            if(cg[i].v>=mid) {
                tp[--rr]=cg[i];
                add(cg[i].pos,cg[i].f);
            }
            else tp[++ll]=cg[i];
        }
        int tr=rr,trr=rx;
        for(int i=rr;i<=r;i++) add(tp[i].pos,-tp[i].f);
        for(int i=l;i<=ll;i++) cg[i]=tp[i]; 
        for(int i=r;i>ll;i--) cg[i]=tp[tr++];
        for(int i=ql;i<=lx;i++) q[i]=t[i];
        for(int i=qr;i>lx;i--) q[i]=t[trr++];
        cdq(el,mid-1,l,ll,ql,lx); 
        cdq(mid,er,rr,r,rx,qr);   
    } 
    
    int main() {
        while(scanf("%d",&n)==1) {
            int el=1e9,er=0;
            for(int i=1;i<=n;i++) {
                read(v[i]); 
                el=min(el,v[i]); er=max(er,v[i]); 
                cg[i]=node(i,i,v[i],1);
            }
            read(m); cq=0;
            for(int i=1;i<=m;i++) {
                int o,x,y,k;
                read(o); read(x); read(y);
                if(o==1) {
                    cg[++n]=node(n+i,x,v[x],-1);
                    cg[++n]=node(n+i,x,y,1); v[x]=y;
                    el=min(el,y); er=max(er,y); 
                }
                else {
                    read(k);
                    q[++cq]=qs(cq,n+i,x,y,y-x+1-k+1);
                }
            }
            cdq(el,er,1,n,1,cq);
            for(int i=1;i<=cq;i++) printf("%d
    ",ans[i]); 
        }
        return 0;
    }
    /*
    5
    7 1 9 9 5 
    1
    2 3 3 1
    */
    View Code

     

  • 相关阅读:
    linux开机启动服务的修改与查看
    我从百度来30万IP的经验
    JavaScript静态页面值传递之Cookie篇
    采用HttpModules来重写URLs(实践篇)
    JavaScript,5种调用函数的方法
    [JS]详尽解析window.event对象
    mysql锁定单个表的方法
    mysql常见错误提示及解决方法
    浏览器Chrome 3.0.195.21 Final
    svn windows和linux安装笔记
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8399184.html
Copyright © 2020-2023  润新知