把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

qzezoj 1588 队列重构(加强版)

题面传送门
\(90\)分做法见这里
正解是线段树+分治。
我们尝试在线段树上跑分治,则维护线段树每个节点的有几个位置没被选两边跑分治就好了。
代码实现:

#include<cstdio>
using namespace std;
int n,sum[4000039],now[1000039],a[1000039],b[1000039];
inline void read(register int &x) {
    x=0;register char s=getchar();
    while(s<'0'||s>'9')s=getchar();
    while(s>='0'&&s<='9')x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
inline void print(register int x) {
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
inline int jianshu(register int l,register int r,register int now){
    if(l==r)return sum[now]=1;
    register int m=(l+r)>>1;
    return sum[now]=jianshu(l,m,now<<1)+jianshu(m+1,r,now<<1|1);
}
int main(){
    register int i,l,r,nows,x,y,ans;
    read(n);
    for(i=1;i<=n;i++) read(x),read(y),now[x]=y;
    jianshu(1,n,1);
    for(i=1;i<=n;i++){
        x=now[i]+1;
        l=1;r=n;nows=1;
        while(l!=r){
            if(sum[nows<<1]>=x) r=(l+r)>>1,nows<<=1;
            else x-=sum[nows<<1],l=((l+r)>>1)+1,nows=nows<<1|1;
        }
        ans=l;
        a[ans]=i;b[ans]=now[i];
        l=1;r=n;nows=1;
        while(l!=r){
            sum[nows]--;
            if(ans<=((l+r)>>1))  r=(l+r)>>1,nows<<=1;
            else l=((l+r)>>1)+1,nows=nows<<1|1;
        }
        sum[nows]--;
    }
    for(i=1;i<=n;i++) print(a[i]),putchar(' '),print(b[i]),putchar('\n');
}
posted @ 2020-04-11 16:31  275307894a  阅读(61)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end