这道题放了很久还是回来补了

D 天才麻将少女KPM SRM 07

背景&&描述

天才麻将少女KPM立志要在日麻界闯出一番名堂。
    KPM上周叒打了n场麻将,但她这次又没控分,而且因为是全市参与的麻将大赛,所以她的名次范围是0..10^5。
    名次可能等于0是因为KPM那场没去打= =
    没去打就意味着无限的可能性。
    KPM叒想要让自己的名次严格递增。为了避免被妹子怀疑,她只能把没打的比赛的名次改成T..R中的整数
    当然,n场全部严格递增是很难做到的。你只需要求出可能的最长递增子序列长度就好了。

输入格式

第一行三个整数n,T,R。
第二行n个整数,表示n场的排名。

输出格式

可能的最长递增子序列长度。

样例输入

5 1 4
3 0 5 9 2

样例输出

4

数据范围与约定

  • 对于100%的数据:

先贴一波大爷的题解

做严格上升 f【i】表示当前以i结尾的最大答案

a【j】!=0照常 a【j】==0的话就有f【i】=max(f【i】,f【i-1】)+1;(L<=i<=R)

f【i-1】一定>=f【i】所以相当于+1后整体平移一格 用平衡树就可以实现了

所以实际涉及到的操作有区间更新 单点插入和删除

————————————————————————————————————

接下来自然就是我自己的写法咯‘

f【w】表示考虑到当前点的以w结尾的最长上升字序列的长度

其实f数组可以写成f【x】【i】 表示到第x个数以i结尾的最长上升子序列

但是明显我们用到的只有上一个点的信息 所以完全可以压成一维

实际上开成两维空间也接受不了

但是啊 因为我懒得弄区间操作所以我写成了差分 即树上维护的是f【i】-f【i-1】

这样转换之后就只涉及到单点插入修改

在涉及到的区间左端点位置插入一个值 删除右端点右侧的第一个1

至于为什么请听我细细道来...
首先我们考虑f【i-1】+1和f【i】的关系

0<=f【i】-f【i-1】<=1 这个很好证明吧

f【i】是一定>f【i-1】的 如果f【i】-f【i-1】大于1 那么序列不可能严格递增

所以相当于直接将区间+1后挪动一个位置 将取max直接改为赋值

因为我维护的是差分 就相当于在左端点处插入一个点,删去右端点后面的第一个1

至于左右端点 如果a【i】是0 自然是 l——r 否则就是那一个点咯(一个点也是区间)

至于为什么要删除 因为他能够影响到的就只能到右端点后第一个1 这个自己画图模拟一下咯

所以我们平衡树需要维护的就是区间是否有1 以及子树size

splay删除实在太恶心 所以我写了fhq treap

单点插入容易 分裂合并一波就好了

删除右端点后的第一个点就需要用到我们维护的——区间内是否有1

先把右端点后的区间分裂出来 考虑当前点x

if x的左子树有1 那么就往左子树跑

else if x本身有1 就删除x

else 往右子树跑

至于怎么删除x 把他的左右子树合在一起(merge)就好了

最后的答案就统计一下到0——a【i】的最大值之间有多少个1就行了

可能讲完这些还不是很清楚 不然来模拟一波样例吧

5 1 4
3 0 5 9 2

f【】的变化

000000000

001111111

111222222

111233333

111233334

122233334

f【】的差分变化

000000000

001000000

100100000

100110000000110001

110010001

100110001

这样思路应该清晰了

顺便口胡一句 fhq treap 真的难调.......

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e5+;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
struct node{
node *l,*r;
int h,f,sz,rnd;
void init(){h=; sz=; rnd=rand();}
void up(){
sz=; f=h;
if(l) sz+=l->sz,f=f|(l->f);
if(r) sz+=r->sz,f=f|(r->f);
}
void split(node*&lw,node*&rw,int k){
if(!this){lw=; rw=; return ;}
int ls=l?l->sz:;
if(k<=ls){
l->split(lw,l,k);
rw=this;
}
else{
r->split(r,rw,k-ls-);
lw=this;
}
up();
}
}tr[*M],*rt;
node* merge(node*a,node*b){
if(!a) return b;
if(!b) return a;
if(a->rnd>b->rnd){
a->r=merge(a->r,b);
a->up();
return a;
}{
b->l=merge(a,b->l);
b->up();
return b;
}
}
void modify(node*&x){
if(!x||!(x->f)) return ;
if(x->l&&(x->l->f)) modify(x->l);
else if(x->h==){
if(x->l&&x->r) x=merge(x->l,x->r);
else if(x->l) x=x->l;
else x=x->r;
return ;
}
else modify(x->r);
x->up();
}
int mx,n,l,r,k,cnt=M,ans;
int query(node *x){
if(!x) return ;
int sum=x->h;
if(x->l) sum+=query(x->l);
if(x->r) sum+=query(x->r);
return sum;
}
int main()
{
// freopen("input.in","r",stdin);
for(int i=;i<=M;i++) tr[i].init(),rt=merge(rt,tr+i);
n=read(); l=read(); r=read();
for(int i=;i<=n;i++){
k=read();
if(k) mx=max(mx,k);else mx=max(mx,r);
tr[++cnt].init();
tr[cnt].h=tr[cnt].f=;
node *p1,*p2,*p3;
if(!k){
rt->split(p2,p3,r-);
p2->split(p1,p2,l-);
modify(p3);
rt=merge(merge(p1,tr+cnt),merge(p2,p3));
}
else{
rt->split(p1,p2,k-);
modify(p2);
rt=merge(merge(p1,tr+cnt),p2);
}
}
node *p1,*p2;
rt->split(p1,p2,mx);
ans=query(p1);
printf("%d\n",ans);
return ;
}

汕头市队赛 SRM 07 D 天才麻将少女kpm的更多相关文章

  1. 汕头市队赛 SRM 07 B 好玩的麻将

    B 好玩的麻将 SRM 07 背景&&描述 天才麻将少女KPM立志要在日麻界闯出一番名堂.     KPM上周又打了n场麻将,又控了分使得自己的排名是1..n的一个排列.     但她 ...

  2. 汕头市队赛 SRM 07 C 整洁的麻将桌

    C 整洁的麻将桌 SRM 07 背景&&描述 天才麻将少女KPM立志要在日麻界闯出一番名堂.     KPM上周双打了n场麻将,但她这次没控分,而且因为是全民参与的麻将大赛,所以她的名 ...

  3. 汕头市队赛 SRM 07 A 你的麻将会排序吗

    A 你的麻将会排序吗 SRM 07 曾经有过一些沉迷日麻的小孩纸,后来呀,他们都去寻找自己的世界了. kpm也是这样的小孩纸.他想有一只自动整理牌的机器.当麻将以给定的顺序进入机器时,通过机器的运转, ...

  4. 汕头市队赛 SRM 06 B 起伏的排名

    B 起伏的排名 SRM 06 背景&&描述 天才麻将少女KPM立志要在日麻界闯出一番名堂.     在上个星期她打了n场麻将,每场麻将都有n名玩家.KPM自然记得自己的n次排名.   ...

  5. 【SRM-07 D】天才麻将少女KPM

    Description 天才麻将少女KPM立志要在日麻界闯出一番名堂.KPM上周叒打了n场麻将,但她这次又没控分,而且因为是全市参与的麻将大赛,所以她的名次范围是0..10^5.名次可能等于0是因为K ...

  6. CH暑假欢乐赛 SRM 07 天才麻将少女KPM(DP+treap)

    首先LIS有个$O(n^2)$的DP方法 $f(i,j)$表示前i个数,最后一个数<=j的LIS 如果$a_i!=0$则有 如果$a_i=0$则有 注意因为$f(i-1,j)\leq f(i-1 ...

  7. 汕头市队赛SRM 20 T2不净的圣杯

    不净的圣杯 SRM 20 背景 作为一张BUG级别的卡,官方打算把它修改得人畜无害一些…… 虽然名字还没想好,但是能力大概是对敌方所有单位造成d点伤害,d为自己牌组中所有卡的编号的最大公约数.这无疑是 ...

  8. 汕头市队赛 SRM 06 C 秀恩爱

    C 秀恩爱 SRM 06 背景&&描述         KPM坐在直升机上俯瞰小渔村景象.         渔村可看作二维平面,密密麻麻地到处都是单身狗,KPM当前所在坐标为(sx,s ...

  9. 汕头市队赛 SRM 06 A 撕书

    A 撕书 SRM 06 背景&&描述 游行寺汀正在杀书.         书总共有n页,每页都可以看作是一个小写英文字母,所以我们可以把书看成长度为n的字符串s.         琉璃 ...

随机推荐

  1. ERP启动会

    一个信念: 只许成功,不许失败. 二个原则: 第一个原则是“业务为主,IT为辅”的实施原则: 第二个原则是“循序渐进,持续改善”的工作原则. 三点要求: 第一点,各分公司.各部门的负责人要将ERP信息 ...

  2. Linux下创建和删除软、硬链接 可临时处理空间不足

    在Linux系统中,内核为每一个新创建的文件分配一个Inode(索引结点),每个文件都有一个惟一的inode号.文件属性保存在索引结点里,在访问文件时,索引结点被复制到内存在,从而实现文件的快速访问. ...

  3. Java编程,打印昨天的当前时刻

    public class Demo {  /*  * Java编程,打印昨天的当前时刻  */ public static void main(String[] args){  Calendar ca ...

  4. android 面试准备基础题

    1.    请描述下Activity的生命周期. 必调用的三个方法:onCreate() --> onStart() --> onResume(),用AAA表示 )父Activity启动子 ...

  5. Windows 10更新时出现0x80070422错误

    Windows更新 更新状态 安装更新时出现一些问题,但我们稍后会重试.如果你继续看到此错误,并想要搜索Web或联系支持人员以获取相关信息,一下信息可能会对你有帮助:(0x80070422) 分析原因 ...

  6. Mac上配置idea的项目上传到GitHub

    1.安装git,Mac默认已经安装了Git,可以通过命令git —version查询一下. 2.创建SSH KEY(如果已经创建过,则不用再次创建.查看~/.ssh/id_rsa.pub是否存在) 生 ...

  7. Android: 创建一个AlertDialog对话框,必须按确定或取消按钮才能关闭对话框,禁止按[返回键]或[搜索键]关闭

    AlertDialog.Builder builder = new Builder(this); builder.create().show(); 这样显示出来的对话框,当用户按返回键或搜索键时,这个 ...

  8. 1: java开发_""和null的区别

    原文地址:http://www.cnblogs.com/hongten/archive/2012/11/08/java_null.html 在代码中: 1 //name可以为"", ...

  9. 有趣的canvas

    最近看了一本canvas的书,里面对canvas的一些基本知识讲的很详细.相比于一个div加点颜色,我臭屁的觉得使用canvas画长方形正方形圆形之类的是大才小用. 下面我放几个canvas还不错的功 ...

  10. 一个小时学会Oracle数据库

    一.数据库概要 二.Oracle简介 三.安装运行Oracle数据库 四.使用GUI操作MySQL 五.使用SQL访问Oracle数据库 六.下载程序.帮助.视频 Oracle视频下载(111班):h ...