题目

P3506 [POI2010]MOT-Monotonicity 2

第一次切掉没题解的题\(qwq\)

做法

首先确定\(a_i\)的位置后显然就能确定\(a_{i+1}\)的位置,建一棵权值线段树,维护\(<,=,>\)三种情况

考虑确定\(a_{i}\)的位置

  1. 在\([min,a_{i}-1]\)中找\(<\)的最大值

  2. 在\([a_{i}+1,max]\)中找\(>\)的最大值

  3. 找\([a_{i},a_{i}]\)的\(=\)的值(其实不用线段树,开个数组就能维护)

  4. 比较三个值,假定最大值为\(val\),则更新\([a_{i},a_{i}]\)中\(s[(val-1)\%k+1]\)的值(想一想为什么只更新一个符号的值就能保证正确性?)

这题的难点解决了,至于输出方案,如果你做多了这样的题自然能想到开个数组存每次的状态,然后再开个数组存前驱

代码写得比较乱,重载这些大家自己加吧

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef int LL;
const LL maxn=1500009;
inline LL Read(){
LL x(0),f(1); char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
struct node{
LL mx,mxi,tot;
};
struct Tree{
node t[4];
LL son[2];
}tree[maxn];
LL nod;
node Query(LL now,LL l,LL r,LL lt,LL rt,LL opt){
if(!now||lt>rt)
return (node){0,0,0};
if(lt<=l&&rt>=r)
return tree[now].t[opt];
node ans=(node){0,0,0};
LL mid=(l+r)>>1;
if(lt<=mid)
ans=Query(tree[now].son[0],l,mid,lt,rt,opt);
if(rt>mid){
node tmp=Query(tree[now].son[1],mid+1,r,lt,rt,opt);
if(ans.mx<tmp.mx)
ans=tmp;
}
return ans;
}
inline void Update(LL now,LL opt){
LL son0(tree[now].son[0]),son1(tree[now].son[1]);
if(tree[son0].t[opt].mx>tree[son1].t[opt].mx)
tree[now].t[opt]=tree[son0].t[opt];
else
tree[now].t[opt]=tree[son1].t[opt];
}
inline void Change(LL &now,LL l,LL r,LL opt,LL goal,LL val,LL tot){
if(!now){
now=++nod;
if(l==r)
for(LL i=1;i<=3;++i)
tree[now].t[i]=(node){0,l,0};
}
if(l==r){
if(tree[now].t[opt].mx<val)
tree[now].t[opt].mx=val,
tree[now].t[opt].tot=tot;
return;
}
LL mid=(l+r)>>1;
if(goal<=mid)
Change(tree[now].son[0],l,mid,opt,goal,val,tot);
else
Change(tree[now].son[1],mid+1,r,opt,goal,val,tot);
Update(now,opt);
}
LL n,k,root,ans,last,_min,_max;
LL pre[maxn],a[maxn],c[maxn],ch[maxn],w[maxn];
void Write(LL now){
if(!now)
return;
Write(pre[now]);
printf("%d ",w[now]);
}
struct LS{
LL id,val;
}b[maxn];
inline bool cmp1(LS x,LS y){
return x.val<y.val;
}
int main(){
n=Read(),k=Read();
for(LL i=1;i<=n;++i)
b[i]=(LS){i,Read()},
c[i]=b[i].val;
sort(b+1,b+1+n,cmp1);
LL num(0);
for(LL i=1,last=-1;i<=n;++i){
if(last!=b[i].val)
last=b[i].val,
++num;
a[b[i].id]=num;
}
_min=1,_max=num; for(LL i=1;i<=k;++i){
char c;
scanf(" %c",&c);
if(c=='<')
ch[i]=1;
else if(c=='>')
ch[i]=3;
else
ch[i]=2;
}
LL tot(0),last;
for(LL i=1;i<=n;++i){
node ans1=Query(root,_min,_max, _min,a[i]-1,1),
ans2=Query(root,_min,_max, a[i],a[i] ,2),
ans3=Query(root,_min,_max, a[i]+1,_max,3);
++ans1.mx,++ans2.mx,++ans3.mx; if(ans1.mx<ans2.mx) ans1=ans2;
if(ans1.mx<ans3.mx) ans1=ans3; LL sum(ans1.mx);
w[++tot]=c[i],
pre[tot]=ans1.tot,
Change(root,_min,_max,ch[(sum-1)%k+1],a[i],sum,tot);
if(sum>ans)
ans=sum,
last=tot;
}
printf("%d\n",ans);
Write(last);
return 0;
}/*
20 5
2 4 3 1 3 5 3 8 9 2 1 20 3 5 9 1 2 4 5 3
< > = < > 11
2 4 3 3 5 3 9 1 1 4 3
*/

最新文章

  1. Lintcode 150.买卖股票的最佳时机 II
  2. 1014 : Trie树 hihocoder
  3. Android中shell命令语句
  4. rosetta common sh: mpiCC command not found解决方法
  5. android图片拖动缩放
  6. .NET破解之轻量万能自定义信息管理系统
  7. nyoj 203 三国志 dijkstra+01背包
  8. QEMU Guest Agent
  9. 【剑指offer】二叉搜索树的后序遍历序列
  10. 复习了下自定义style的使用
  11. mysql支持emoji解决办法
  12. PHP MYSQL数据字典
  13. 关于他们回答的 &quot;怎样在桌面建一个python GUI的快捷方式&quot; 这个问题
  14. 豹哥嵌入式好讲堂:ARM Cortex-M调试过程探析(1)- 4线接口标准(JTAG)
  15. Android系统服务详解-android学习之旅(95)
  16. DWM1000 三基站一标签定位HEX
  17. MySQL中MyISAM与InnoDB的主要区别对比
  18. 287. Find the Duplicate Number 找出数组中的重复数字
  19. Docker 网络管理
  20. 通过SIMPLE_DEV_PM_OPS定义suspend和resume函数【转】

热门文章

  1. 运行./cpp.sh,显示command not found
  2. CSRF介绍与应对以及Java代码示例
  3. Android的View 事件传递
  4. Java银行调度系统
  5. Codeforces 14D Two Paths 树的直径
  6. Hadoop之MapReduce的两种任务模式
  7. Python调用API接口的几种方式 数据库 脚本
  8. memcached在Java中的应用以及magent的配置-每天进步一点点
  9. PowerBuilder--Aes128加解密
  10. 承载(Host)通用语言执行时