题目链接

\(Description\)

\(Solution\)

还是看代码好理解吧。

为了方便,我们将x坐标左右反转,再将所有高度取反,这样依然是维护从左到右的LIS,但是每次是在右边删除元素。

这样对于在p刚种的树,最多只有9棵树比它高,即它只会转移到这9棵树,除这9棵树外,它可以从1~p-1的任何树转移(其它9棵树除比它高的外 同样可以从它前面任何树转移)。

我们把这9棵树的DP值暴力删掉,然后从低到高 从1~pos[h]-1转移并更新。按高度更新就只需要考虑位置合不合法了。

我们对位置建线段树维护每个位置的DP值,就只有单点修改、区间max。

对于砍掉右数第k棵树,设位置为p,因为只有右边最多9棵树从它转移,同样将它们的DP值暴力删掉,然后删掉位置p的DP值。

但是右边10棵树不一定是最高的,虽然它们可以从前面所有树转移,但还要满足高度小于它们。

这可以二维线段树。但是我们只需要用另一棵线段树对每个高度维护同样的DP值(不同位置高度不同),就可以从左到右,直接用线段树查询并更新了。

这样在一棵线段树上更新完DP值后在另一棵上改一下即可。

复杂度\(O(10n\log n)\)。

总结:是最高的10棵就在维护位置DP值的线段树上转移,是最靠右的10棵就在维护高度DP值的线段树上转移。最后更新一下另一棵的DP值(都维护一样的)。

//840ms	12800KB
#include <set>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 50000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=2e5+15; int pos[N],h[N];
std::set<int> st;
char IN[MAXIN],*SS=IN,*TT=IN;
struct Segment_Tree
{
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
#define S N<<2
int f[N],mx[S];
#undef S #define Update(rt) mx[rt]=std::max(mx[ls],mx[rs])
void Modify(int l,int r,int rt,int p,int v)
{
if(l==r) {mx[rt]=v; return;}
int m=l+r>>1;
if(p<=m) Modify(lson,p,v);
else Modify(rson,p,v);
Update(rt);
}
int Query(int l,int r,int rt,int R)
{
if(r<=R) return mx[rt];
int m=l+r>>1;
if(m<R) return std::max(Query(lson,R),Query(rson,R));
return Query(lson,R);
}
void Insert(int p,int n)//对于新插入的p查询DP值并更新
{
Modify(0,n,1,p,f[p]=Query(0,n,1,p-1)+1);
}
}Tp,Th; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
#define Sp 0,n,1
#define Sh 0,m+10,1
int n=read(),m=read();//pos[i]:高i的树的位置 h[i]:i位置的树的高度
for(int t=1; t<=m; ++t)
if(read()==1)//plant
{
int p=n-read()+1,ht=t+10-read();
pos[ht]=p, h[p]=ht, st.insert(p);
for(int i=ht+1; i<=ht+9; ++i)
if(pos[i]) Tp.Modify(Sp,pos[i],0);
for(int i=ht; i<=ht+9; ++i)
if(pos[i])
{
Tp.Insert(pos[i],n);
Th.f[i]=Tp.f[pos[i]];
Th.Modify(Sh,i,Th.f[i]);
}
printf("%d\n",Tp.mx[1]);
}
else
{
int k=read();
std::set<int>::iterator it=st.end();
while(k--) --it, Th.Modify(Sh,h[*it],0);
Tp.Modify(Sp,*it,0), pos[h[*it]]=0;
for(st.erase(it++); it!=st.end(); ++it)
{
Th.Insert(h[*it],m+10);
Tp.f[*it]=Th.f[h[*it]];
Tp.Modify(Sp,*it,Tp.f[*it]);
}
printf("%d\n",Tp.mx[1]);
} return 0;
}

Codeforces.264E.Roadside Trees(线段树 DP LIS)的更多相关文章

  1. Codeforces.833B.The Bakery(线段树 DP)

    题目链接 \(Description\) 有n个数,将其分为k段,每段的值为这一段的总共数字种类,问最大总值是多少 \(Solution\) DP,用\(f[i][j]\)表示当前在i 分成了j份(第 ...

  2. CodeForces–833B--The Bakery(线段树&&DP)

    B. The Bakery time limit per test 2.5 seconds memory limit per test 256 megabytes input standard inp ...

  3. 线段树解LIS

    先是nlogn的LIS解法 /* LIS nlogn解法 */ #include<iostream> #include<cstring> #include<cstdio& ...

  4. [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)

    [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...

  5. Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    [题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...

  6. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  7. Buses and People CodeForces 160E 三维偏序+线段树

    Buses and People CodeForces 160E 三维偏序+线段树 题意 给定 N 个三元组 (a,b,c),现有 M 个询问,每个询问给定一个三元组 (a',b',c'),求满足 a ...

  8. CodeForces 877E DFS序+线段树

    CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...

  9. [Codeforces 1199D]Welfare State(线段树)

    [Codeforces 1199D]Welfare State(线段树) 题面 给出一个长度为n的序列,有q次操作,操作有2种 1.单点修改,把\(a_x\)修改成y 2.区间修改,把序列中值< ...

随机推荐

  1. Win7 启动修复

    先让我们看一下windows7的启动过程的常识:电脑加电后,首先是启动BIOS程序,BIOS自检完毕后,找到硬盘上的主引导记录MBR,MBR读取DPT(分区表),从中找出活动的主分区,然后读取活动主分 ...

  2. 笔记软件 notion

    笔记软件 notion :     https://www.notion.so 注册:zengxinle@126.com     团队:Hopesun

  3. xargs -i和-I的区别【转】

    xargs与find经常结合来进行文件操作,平时删日志的时候只是习惯的去删除,比如  # find . -type f -name "*.log" | xargs rm -rf * ...

  4. mysql删除数据库文件ibdata1后引发的故障

    进行性能测试是发现大量报错: Duplicate entry主键重复 可以看到mysql数据库中已经没有innodb引擎启动信息了 之前发现ibdata1占用了大量硬盘,为了省出空间删除了数据库ibd ...

  5. Eclipse与github整合

    Eclipse与github整合 Windows系统下: github官方指南:https://help.github.com/articles/set-up-git Git?是个正快速成长的版本控制 ...

  6. [java]用md5来判断两个文件是否完全相同

    1. 前言 由于相比较两张图片是否是相同,如果通过像素点比较感觉速度比较慢,当很多图片进行比较时,效率就低很多了.由于每个文件md5基本上是唯一的,所以用获取文件的md5来判断是否相同文件. 2. 代 ...

  7. swift的一些知识点(不断完善中)

    首先,隆重推荐文章http://www.infoq.com/cn/articles/swift-brain-gym-optional swift 烧脑体操!目前有4篇文章,说的都很好! 1. 应该充分 ...

  8. PYTHON-TCP 粘包

    1.TCP的模板代码 收发消息的循环 通讯循环 不断的连接客户端循环 连接循环 判断 用于判断客户端异常退出(抛异常)或close(死循环) 半连接池backlog listen(5) 占用的是内存空 ...

  9. Route pattern cannot reference variable name more than once

    在用 Laravel Backpack 写一个定制化的 CRUD 页面.例如,一个指定店铺所拥有的商品的 CRUD 页面. 起初路由我是这样写的 CRUD::resource('products-of ...

  10. linux 卸载自带apache httpd 安装apache httpd

    一.卸载自带apache httpd 1.关闭httpd服务:/etc/init.d/httpd stop 2.列出相关程序包:rpm -qa|grep httpd 3.卸载命令:rpm -e --n ...