前鬼后鬼的守护

题目大意

给定序列x。
将xi修改成x’要付出|x’-xi|的代价。
求最小代价使得xi<=xi+1

维护函数

设DP,Fi(x)表示把第i个修改成x使得前i个递增的最小代价。
Fi(x)=|x-xi|+min(Fi-1(1~x))
Fi就是函数嘛,容易观察出还是许多一次函数组成的单调函数。
每次就是加上两段一次函数,那个取min是把斜率大于0的直线改为平板。splay维护即可。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=500000+10,maxd=1e9;
int father[maxn*2],tree[maxn*2][2],kk[maxn*2],adk[maxn*2],L[maxn*2],sta[maxn*2];
ll bb[maxn*2],adb[maxn*2];
int i,j,k,l,t,n,m,tot,root,top;
ll ans;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
void mark(int x,int k,ll b){
    if (!x) return;
    kk[x]+=k;adk[x]+=k;
    bb[x]+=b;adb[x]+=b;
}
void clear(int x){
    if (adk[x]||adb[x]){
        mark(tree[x][0],adk[x],adb[x]);
        mark(tree[x][1],adk[x],adb[x]);
        adk[x]=adb[x]=0;
    }
}
void remove(int x,int y){
    top=0;
    while (father[x]!=y){
        sta[++top]=x;
        x=father[x];
    }
    while (top){
        clear(sta[top]);
        top--;
    }
}
int pd(int x){
    return tree[father[x]][1]==x;
}
void rotate(int x){
    int y=father[x],z=pd(x);
    father[x]=father[y];
    if (father[y]) tree[father[y]][pd(y)]=x;
    tree[y][z]=tree[x][1-z];
    if (tree[x][1-z]) father[tree[x][1-z]]=y;
    tree[x][1-z]=y;
    father[y]=x;
    if (y==root) root=x;
}
void splay(int x,int y){
    remove(x,y);
    while (father[x]!=y){
        if (father[father[x]]!=y)
            if (pd(x)==pd(father[x])) rotate(father[x]);else rotate(x);
        rotate(x);
    }
}
/*int find(int x,int y){
    if (!x) return 0;
    if (y>=L[x]){
        int t=find(tree[x][1],y);
        if (t) return t;else return x;
    }
    else return find(tree[x][0],y);
}*/
void changemin(){
    int j=0,k=root;
    ll l;
    while (1){
        if (!k) break;
        clear(k);
        if (kk[k]<=0) k=tree[k][1];
        else{
            j=k;
            k=tree[k][0];
        }
    }
    if (j){
        splay(j,0);
        L[++tot]=L[j];
        l=(ll)kk[j]*L[j]+bb[j];
        kk[tot]=0;
        bb[tot]=l;
        tree[tot][0]=tree[j][0];
        if (tree[j][0]) father[tree[j][0]]=tot;
        root=tot;
    }
}
int main(){
    freopen("chen.in","r",stdin);freopen("chen.out","w",stdout);
    n=read();
    root=tot=1;
    L[1]=1;
    fo(i,1,n){
        t=read();
        //k=find(root,t);
        j=0;k=root;
        while (k){
            if (L[k]<=t){
                j=k;
                k=tree[k][1];
            }
            else k=tree[k][0];
        }
        k=j;
        splay(k,0);
        mark(tree[k][0],-1,t);
        mark(tree[k][1],1,-t);
        if (L[k]==t){
            kk[k]++;
            bb[k]-=(ll)t;
        }
        else{
            L[++tot]=L[k];
            tree[tot][0]=tree[k][0];
            if (tree[k][0]) father[tree[k][0]]=tot;
            tree[k][0]=tot;
            father[tot]=k;
            L[k]=t;
            kk[tot]=kk[k]-1;
            bb[tot]=bb[k]+(ll)t;
            kk[k]++;
            bb[k]-=(ll)t;
        }
        changemin();
    }
    k=root;
    while (tree[k][1]){
        clear(k);
        k=tree[k][1];
    }
    ans=(ll)kk[k]*maxd+bb[k];
    printf("%lld\n",ans);
}
### Linux UDEV机制与USB设备自动挂载 在Linux操作系统中,`udev` 是用户空间中的设备管理器,负责管理和命名系统上的硬件设备节点。当检测到新设备连接时(如U盘),会触发相应的事件处理程序来加载驱动并创建对应的设备文件。 #### udev的工作原理 `systemd-udevd`服务作为守护进程运行,在内核通过netlink socket通知有新的硬件变动时立即响应。对于每一个被识别出来的设备,该服务都会读取位于 `/usr/lib/udev/rules.d/`, `/run/udev/rules.d/` 和 `/etc/udev/rules.d/` 目录下的规则文件[^1]。这些规则定义了如何针对特定类型的设备执行操作,比如设置权限、重命名设备节点或是调用外部脚本等。 为了支持热插拔功能,每当有一个USB存储设备插入计算机时: - 内核探测到新设备并向 `systemd-udevd` 发送消息; - `systemd-udevd` 查找匹配的规则并将属性应用给这个新发现的设备; - 如果存在配置好的自动化行为,则按照设定启动相应流程;例如可以是挂载分区或将媒体图标显示于桌面环境上。 #### 自动挂载U盘的方法 要实现U盘插入后的自动挂载,通常有两种方式:一是利用图形界面自带的功能,二是编写自定义的 `udev` 规则配合其他工具完成此目的。下面介绍基于命令行环境下的一种方法——借助 `udisks2` 工具包及其配套的服务来进行自动化的磁盘管理。 首先安装必要的软件包: ```bash sudo apt-get install udisks2 gvfs-backends ``` 接着编辑或新建一条适用于所有可移动介质的通用规则,保存至 `/etc/udev/rules.d/99-usb-auto-mount.rules` 文件中: ```plaintext ACTION=="add", SUBSYSTEMS=="usb", ENV{ID_TYPE}=="disk", RUN+="/bin/systemctl start udiskie@%k.service" ``` 上述规则表示只要检测到了新增加的USB磁盘就激活名为 `udiskie@[device_name].service` 的实例化单元。这里假设已经预先准备好了模板形式的服务定义文件用于实际挂载动作。 最后重启 `systemd-udevd` 来使更改生效: ```bash sudo systemctl restart systemd-udevd ``` 现在每次插入兼容的USB闪存盘或其他外置硬盘之后都应该能够看到它们被正确识别并且自动挂在指定位置上了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值