标签:修改 read update std ace val name merge swa
左偏树裸题(也可以用dp做)
对于一段有连续性的不合法区间,把他们全都变成中位数显然是最好的。
假如我们要实现连续不下降,那么:
对于后一段区间的中位数比前一段的中位数小,那么把这两段区间合并,全部修改为这两段区间的中位数,否则的话就不用管。
假如我们要实现连续不上升,那么我们把小于号改为大于号就好了……
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 2020
using namespace std;
int n,a[N],ans,tmp,q[N],b[N],l,now;
struct node
{
node *ls,*rs;
int val,dist,siz;
node(): ls(NULL),rs(NULL),val(0),dist(0),siz(0){}
node(int x): ls(NULL),rs(NULL),val(x),dist(0),siz(1){}
node* update()
{
if (!ls || ls->dist<rs->dist) swap(ls,rs);
dist=rs?rs->dist+1:0;
siz=(ls?ls->siz:0)+(rs?rs->siz:0)+1;
return this;
}
}*tre[N];
int read()
{
int ans=0,fu=1;
char j=getchar();
for (;(j<‘0‘ || j>‘9‘) && j!=‘-‘;j=getchar()) ;
if (j==‘-‘) fu=-1,j=getchar();
for (;j>=‘0‘ && j<=‘9‘;j=getchar()) ans*=10,ans+=j-‘0‘;
return ans*fu;
}
node* merge(node *x,node*y)
{
if (!x) return y;
if (!y) return x;
if (x->val<y->val) swap(x,y);
x->rs=merge(x->rs,y);
return x->update();
}
void pop(node *&x,int t)
{
while ((x->siz)>((t+1)/2))
x=merge(x->ls,x->rs);
}
int main()
{
n=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=n;i++)
{
b[i]=a[i];
tre[i]=new node(b[i]);
while (l && b[i]<b[q[l]])
{
tre[i]=merge(tre[i],tre[q[l]]);
--l;
pop(tre[i],i-q[l]);
b[i]=tre[i]->val;
}
q[++l]=i;
}
now=1;
l=1;
while (now<=n)
{
b[now]=b[q[l]];
if (now==q[l]) ++l;
++now;
}
for (int i=1;i<=n;i++) ans+=abs(a[i]-b[i]);
memset(tre,0,sizeof(tre));
l=0;
for (int i=1;i<=n;i++)
{
b[i]=a[i];
tre[i]=new node;
while (l && b[i]>b[q[l]])
{
tre[i]=merge(tre[i],tre[q[l]]);
--l;
pop(tre[i],i-q[l]);
b[i]=tre[i]->val;
}
q[++l]=i;
}
now=1;
l=1;
while (now<=n)
{
b[now]=b[q[l]];
if (now==q[l]) ++l;
++now;
}
for (int i=1;i<=n;i++) tmp+=abs(a[i]-b[i]);
printf("%d",min(ans,tmp));
return 0;
}
标签:修改 read update std ace val name merge swa
原文地址:http://www.cnblogs.com/mrha/p/7898477.html