P1533 可怜的狗狗 平衡树

题目背景
小卡由于公务需要出差,将新家中的狗狗们托付给朋友嘉嘉,但是嘉嘉是一个很懒的人,他才没那么多时间帮小卡喂狗狗。

题目描述
小卡家有N只狗,由于品种、年龄不同,每一只狗都有一个不同的漂亮值。漂亮值与漂亮的程度成反比(漂亮值越低越漂亮),吃饭时,狗狗们会按顺序站成一排等着主人给食物。

可是嘉嘉真的很懒,他才不肯喂这么多狗呢,这多浪费时间啊,于是他每次就只给第i只到第j只狗中第k漂亮的狗狗喂食(好狠心的人啊)。而且为了保证某一只狗狗不会被喂太多次,他喂的每个区间(i,j)不互相包含。

输入输出格式
输入格式:
第一行输入两个数n,m,你可以假设n<300001 并且 m<50001;m表示他喂了m次。

第二行n个整数,表示第i只狗的漂亮值为ai。

接下来m行,每行3个整数i,j,k表示这次喂食喂第i到第j只狗中第k漂亮的狗的漂亮值。

输出格式:
M行,每行一个整数,表示每一次喂的那只狗漂亮值为多少。

输入输出样例
输入样例#1:
7 2
1 5 2 6 3 7 4
1 5 3
2 7 1
输出样例#1:
3
2

读题:求静态维护区间第k大,显然可以用主席树o r 莫队算法轻松过去,
但作为一名蒟蒻(其实是懒得动脑筋)表示不会
怎么办,我可以用序列之王splay+一些莫队算法的思想(可能也许叫毛毛虫算法)
离线操作:将每个区间L,R,区间排序(一定记得按原顺序编号),以左端点为第一关键字,右端点为第二关键字,之后再简单的处理一下就行了(建议自己画图与程序一起理解)
具体操作
设置两个之间指针一起向右移动,用splay维护区间删除头元素,插入尾元素,
画个图:
这里写图片描述
上代码:

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int read() {
    int f=1,x=0;
    char c=getchar();
    while (c<'0'||c>'9') {
        if (c=='-') f=-1;
        c=getchar();
    }
    while (c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return f*x;
}
int n,m,g,h,o,p,root,cnt,tot;
const int maxn=3e5+5;
int s[maxn][2],w[maxn],v[maxn],c[maxn],f[maxn];
inline void up(int x) {
    w[x]=w[s[x][0]]+w[s[x][1]]+c[x];
}
inline void rotate(int x) {
    int y=f[x],z=f[y],k=s[y][1]==x;
    s[z][s[z][1]==y]=x;
    f[x]=z;
    s[y][k]=s[x][k^1];
    f[s[x][k^1]]=y;
    s[x][k^1]=y;
    f[y]=x;
    up(y);
    up(x);
}
inline void splay(int x,int g) {
    while (f[x]!=g) {
        int y=f[x],z=f[y];
        if (z!=g)
            (s[z][0]==y)^(s[y][0]==x)?rotate(x):rotate(y);
        rotate(x);
    }
    if (g==0) root=x;
}
inline void find(int x) {
    int u=root;
    if (!u) return;
    while (s[u][x>v[u]]&&x!=v[u])
        u=s[u][x>v[u]];
    splay(u,0);
}
inline int insert(int x) {
    int u=root,ff=0;
    while (u&&v[u]!=x) ff=u,u=s[u][x>v[u]];
    if (u) c[u]++;
    else {
        u=++tot;
        if (ff) s[ff][x>v[ff]]=u;
        s[u][0]=s[u][1]=0;
        f[tot]=ff;
        v[tot]=x;
        c[tot]=1;
        w[tot]=1;

    }
    splay(u,0);
}
inline int next(int x,int ff) {
    find(x);
    int u=root;
    if (v[u]>x&&ff) return u;
    if (v[u]<x&&!ff) return u;
    u=s[u][ff];
    while (s[u][ff^1]) u=s[u][ff^1];
    return u;
}
inline int search(int k) {
    int u=root;
    while (1) {
        int q=s[u][0];
        if (w[q]+c[u]<k)
            k-=w[q]+c[u],u=s[u][1];
        else if (w[q]>=k) u=q;
        else return v[u];
    }
}
inline void del(int x) {
    int l=next(x,0);
    int nxt=next(x,1);
    splay(l,0);
    splay(nxt,l);
    int d=s[nxt][0];
    if (c[d]>1) c[d]--,splay(d,0);
    else s[nxt][0]=0;
}
struct node {
    int x,y,z;
} a[50005];
bool cmp(node x,node y) {
    return (x.x<y.x||(x.x==y.x&&x.y<y.y));
}
int d[300005],t1,w1;
int main() {
    freopen("1.in","r",stdin);
    n=read();
    m=read();
    for (int i=1; i<=n; i++) d[i]=read();
    for (int i=1; i<=m; i++) a[i].x=read(),a[i].y=read(),a[i].z=read();
    sort(a+1,a+m+1,cmp);

    tot=0;
    insert(-2147483647);
    insert(+2147483647);
    t1=0;
    w1=0;
    for (int i=1; i<=m; i++)
        printf("%d %d %d",a[i].x,a[i].y,a[i].z);
    for (int i=a[1].x; i<=a[1].y; i++)
        insert(d[i]);
    printf("%d\n",search(a[1].z+1));

    t1=a[1].x;
    w1=a[1].y;
    for (int i=2; i<=m; i++) {

        while (t1<a[i].x) del(d[t1]),t1++;
        while (w1<a[i].y) insert(d[w1]),w1++;
        printf("%d\n",search(a[i].z+1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fatalzyc/article/details/80356649
今日推荐