[SCOI2014]方伯伯的OJ(线段树)

方伯伯正在做他的Oj。现在他在处理Oj上的用户排名问题。Oj上注册了n个用户,编号为1~n“,一开始他们按照编号排名。

方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号:

1.操作格式为1 x y,意味着将编号为x的用户编号改为y,而排名不变,执行完该操作后需要输出该用户在队列中的位置,数据保证x必然出现在队列中,同时,1是一个当前不在排名中的编号。

2.操作格式为2 x,意味着将编号为x的用户的排名提升到第一位,执行完该操作后需要输出执行该操作前编号为x用户的排名。

3.操作格式为3 x,意味着将编号为x的用户的排名降到最后一位,执行完该操作后需要输出执行该操作前编号为x用户的排名。

4.操作格式为4 k,意味着查询当前排名为k的用户编号,执行完该操作后需要输出当前操作用户的编号。

但同时为了防止别人监听自己的工作,方伯伯对他的操作进行了加密,即将四种操作的格式分别改为了:

  • 1 x+a y+a
  • 2 x+a
  • 3 x+a
  • 4 k+a
  • 其中a为上一次操作得到的输出,一开始a=0。

例如:上一次操作得到的输出是5这一次操作的输入为:1 13 15因为这个输入是经过加密后的,所以你应该处理的操作是1 8 10现在你截获了方伯伯的所有操作,希望你能给出结果。

Solution

调了一晚上。。。菜的不行。

因为数列每次只会变化一个数,所以可以不用splay或fhqtreap,用一颗动态开点线段树就可以完成。

因为我们的移动只关于先插和后插,所以我们线段树的区间为m+n+m对于一个移动,我们先把该点在对应位置删除,再将该数插入前/后对应位置。

与此同时,我们开两个map,一个储存编号对应的位置,一个储存位置对应的编号。

Code

#include<iostream>
#include<cstdio>
#include<map>
#define ls tr[cnt].l
#define rs tr[cnt].r
#define N 200002
using namespace std;
map<int,int>mp,anti_mp;
int tot,id,ans,n,m,root,h,t,x,y;
struct seg{
    int l,r,num;
    bool la;
}tr[N*20];
inline int rd(){
    int x=0;char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c)){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x;
}
inline void pushdown(int cnt,int l1,int l2){
    if(!ls)ls=++tot;if(!rs)rs=++tot;
    tr[ls].num=l1;tr[rs].num=l2;
    tr[cnt].la=0;tr[ls].la=tr[rs].la=1;
}
void add(int &cnt,int l,int r,int x,int tag,int rk){
    if(!cnt)cnt=++tot;
    if(l==r){
        if(tag<0)ans=rk+1,anti_mp.erase(l);
        else anti_mp[l]=id;
        tr[cnt].num-=tag;
        return;
    }
    int mid=(l+r)>>1;
    if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
    if(mid>=x)add(ls,l,mid,x,tag,rk);
    else add(rs,mid+1,r,x,tag,rk+mid-l+1-tr[ls].num);
    tr[cnt].num=tr[ls].num+tr[rs].num;
}
void find(int &cnt,int l,int r,int rk){
    if(!cnt)cnt=++tot;
    if(l==r){
        if(anti_mp.find(l)!=anti_mp.end())ans=anti_mp[l];else ans=l-m;
        return;
    }
    int mid=(l+r)>>1;
    if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
    int num=mid-l+1-tr[ls].num;
    if(num>=rk)find(ls,l,mid,rk);
    else find(rs,mid+1,r,rk-num);
}
void gai(int &cnt,int l,int r,int L,int R){
    if(!cnt)cnt=++tot;
    if(l>=L&&r<=R){
        tr[cnt].num=r-l+1;
        tr[cnt].la=1;
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=L)gai(ls,l,mid,L,R);
    if(mid<R)gai(rs,mid+1,r,L,R);
    tr[cnt].num=tr[ls].num+tr[rs].num;
}
void upd(int &cnt,int l,int r,int x,int y,int rk){
    if(!cnt)cnt=++tot;
    if(l==r){
        anti_mp[l]=y;ans=rk+1;
        return;
    }
    int mid=(l+r)>>1;
    if(tr[cnt].la)pushdown(cnt,mid-l+1,r-mid);
    if(mid>=x)upd(ls,l,mid,x,y,rk);
    else upd(rs,mid+1,r,x,y,rk+mid-l+1-tr[ls].num);
}
int main(){
    n=rd();m=rd();
    gai(root,1,n+2*m,1,m);
    gai(root,1,n+2*m,n+m+1,n+m*2);
    h=m+1;t=n+m;
    for(int i=1;i<=m;++i){
        int tag=rd();x=rd()-ans;
        if(tag==1){
            y=rd()-ans;
            int pos;
            if(mp.find(x)!=mp.end())pos=mp[x];
            else pos=x+m;
            mp[y]=pos;
            upd(root,1,n+2*m,pos,y,0);
        }
        else if(tag==2){
            int pos;
            if(mp.find(x)!=mp.end())pos=mp[x];
            else pos=x+m;
            if(anti_mp.find(pos)!=anti_mp.end())id=anti_mp[pos];
            else id=x;
            add(root,1,n+2*m,pos,-1,0);
            add(root,1,n+2*m,--h,1,0);
            mp[x]=h;
        }
        else if(tag==3){
            int pos;
            if(mp.find(x)!=mp.end())pos=mp[x];
            else pos=x+m;
            if(anti_mp.find(pos)!=anti_mp.end())id=anti_mp[pos];
            else id=x;
            add(root,1,n+2*m,pos,-1,0);
            add(root,1,n+2*m,++t,1,0);
            mp[x]=t;
        }
        else find(root,1,n+2*m,x);
        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ZH-comld/p/9715245.html

时间: 2024-11-09 04:01:02

[SCOI2014]方伯伯的OJ(线段树)的相关文章

BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap

3595: [Scoi2014]方伯伯的OjTime Limit: 6 Sec  Memory Limit: 256 MBSubmit: 102  Solved: 54[Submit][Status] Description 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题. Oj上注册了n个用户,编号为1-",一开始他们按照编号排名.方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为1 x y,意味着将编号为z的用户编号改为V,而排名不变,执行完该操作后需要

[SCOI2014]方伯伯的OJ

题目描述 方伯伯正在做他的Oj.现在他在处理Oj上的用户排名问题.Oj上注册了n个用户,编号为1-n“,一开始他们按照编号排名. 方伯伯会按照心情对这些用户做以下四种操作,修改用户的排名和编号: 1.操作格式为1 x y,意味着将编号为x的用户编号改为y,而排名不变,执行完该操作后需要输出该用户在队列中的位置,数据保证x必然出现在队列中,同时1,是一个当前不在排名中的编号. 2.操作格式为2 x,意味着将编号为x的用户的排名提升到第一位,执行完该操作后需要输出执行该操作前编号为z用户的排名. 3

SCOI2014 方伯伯的OJ onlinejudge

终于用自己的方法水过去了. 本地测慢的一组要三四秒,一共要十几秒,BZOJ貌似一共只让跑6s,于是就还T着的. 一开始没看n<=1e8,想的直接splay+map(splay维护名次,map维护对应标号的节点所在位置) 然后写完看到n的范围 就傻了= = 百度了一下 splay里面的点要包含一段区间 想了半天 自己yy了一个做法: 一开始就一个点:[1,n+2](虚拟节点什么的蛋疼死了,一会+1,一会-1) 于是需要[l,r]中的p点时,就拆成[l,p-1][p,p][p+1,r],可是这样会不

bzoj3594: [Scoi2014]方伯伯的玉米田--树状数组优化DP

题目大意:对于一个序列,可以k次选任意一个区间权值+1,求最长不下降子序列最长能为多少 其实我根本没想到可以用DP做 f[i][j]表示前i棵,操作j次,最长子序列长度 p[x][y]表示操作x次后,最高玉米为y时的最长子序列长度 那么以n棵玉米分阶段,对于每个阶段 f[i][j]=max{p[k][l]}+1,  其中k=1 to j , l=1 to a[i]+j 然后用树状数组维护p[][]的最大值 1 #include<stdio.h> 2 #include<string.h&g

BZOJ 3594 Scoi2014 方伯伯的玉米田 树状数组

题目大意:给定一个序列,可以选择k次区间并将区间内每个数都+1,求操作之后LIS的最大值 我的做法不是标解...5E的复杂度为何跑的飞起... 首先一个显而易见的结论就是我们选择的k次区间右端点都是n时才能保证最优 知道这个我们就可以DP了- - 令f[i][j]表示前i个数上升j次的最大LIS 那么有f[i][j]=max{f[k][l]|k<i,l<=j,a[k]+l<=a[i]+j}+1 看到三维偏序就可以用二维树状数组了- - 时间复杂度O(nklog(max(ai)+k)log

bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化

3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 314  Solved: 132[Submit][Status] Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把这个区间的

bzoj3594 [Scoi2014]方伯伯的玉米田

3594: [Scoi2014]方伯伯的玉米田Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 1437 Solved: 647[Submit][Status][Discuss]Description方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把

3594: [Scoi2014]方伯伯的玉米田

3594: [Scoi2014]方伯伯的玉米田 Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把这个区间的玉米全部拔高1单位高度,他可以进行最多K次这样的操作.拔玉米则可以随意选择一个集合的玉米拔掉.问能最多剩多少株玉米,来构成一排美丽的玉米. Input 第1行包含

BZOJ 3594[Scoi2014]方伯伯的玉米田

题面: 3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1403  Solved: 630[Submit][Status][Discuss] Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可