[线段树]JZOJ 5812

Description

每一个机房中总有一个红太阳。有一天,AmberFrame 来到机房,发现桌上有不知道哪个蒟蒻放上的问 题: 有一个 n 个数的序列,一开始所有的数都是 0,每次可以将一个区间 [l, r](l ≤ r) 内的数 +1,求到达最 终状态的最少操作次数。 AmberFrame 非常强,自然不会把时间花在这种水题上。因此他就把任务交给了你,如果不会做的话,他 可能就会觉得你就是那个放问题的蒟蒻了而把你批判一番了。

Input

第一行包含一个正整数 n,表示序列的长度。
第二行包含 n 个非负整数 a1, a2, ..., an,表示最终的状态。

Output

输出的第一行是一个正整数 m,表示最少的操作次数。 接下来 m 行每行两个正整数 li , ri,表示一次操作。你需要保证 1 ≤ li ≤ ri ≤ n。 保证最少次数 m ≤ 10^5,输出可以以任意顺序输出。

Sample Input

6
2 3 3 3 3 3

Sample Output

3
1 6
1 6
2 6

Data Constraint

Hint

下发样例中第 i 个样例与第 i 组数据范围相符。
对于样例 1,第一个数被加了两次,其他每个数都被加了三次,显然满足条件。

分析

这题我TMD想复杂了

其实只用线段树记录区间最小值下标,然后分治一波就行,显然每次ans累加上最小值min减当前区间已减量delta

比赛时写了一波O3 inline register等卡时操作(并没有什么作用)

#pragma GCC optimize(3)
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#define l(x) t[x].l
#define r(x) t[x].r
#define m(x) t[x].mn
#define s(x) t[x].pos
using namespace std;
const int N=1e5+1;
struct Node {
    int l,r,mn,pos;
}t[4*N];
struct Adep {
    int l,r,dat;
};
int rt=1;
int a[N];
int ansl[N],ansr[N],cnt;
int n;

inline Adep In(int x,int y,int z) {
    Adep a;a.l=x;a.r=y;a.dat=z;
    return a;
}
inline void Build(int x,int l,int r) {
    l(x)=l;r(x)=r;
    if (l==r) {
        m(x)=a[l];
        s(x)=l;
        return;
    }
    int mid=l+r>>1;
    Build(x*2,l,mid);Build(x*2+1,mid+1,r);
    m(x)=m(x*2);s(x)=s(x*2);
    if (m(x)>m(x*2+1)) m(x)=m(x*2+1),s(x)=s(x*2+1);
}

inline int Query(int x,int l,int r) {
    if (l>r(x)||r<l(x)) return 0;
    if (l<=l(x)&&r(x)<=r) return s(x);
    int mid=l(x)+r(x)>>1,ans=0,val=2147483647;
    if (l<=mid) ans=Query(x*2,l,r),val=a[ans];
    if (mid<r) {
        int d=Query(x*2+1,l,r);
        if (val>a[d]) val=a[d],ans=d;
    }
    return ans;
}

inline void Solve() {
    queue <Adep> q;
    while (!q.empty()) q.pop();
    q.push(In(1,n,0));
    while (!q.empty()) {
        Adep d=q.front();q.pop();
        int l=d.l,r=d.r,dt=d.dat;
        int o=Query(rt,l,r),m=a[o],p=0;
        m-=dt;
        while (m) {
            ansl[++cnt]=l;ansr[cnt]=r;
            m--;p++;
        }
        if (l<=o-1) q.push(In(l,o-1,dt+p));
        if (o+1<=r) q.push(In(o+1,r,dt+p));
    }
}

int main() {
    freopen("range.in","r",stdin);
    freopen("range.out","w",stdout);
    scanf("%d",&n);
    for (register int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (register int i=1;i<=4*n;i++) t[i].mn=2147483647;
    a[0]=2147483647;
    Build(rt,1,n);
    Solve();
    printf("%d\n",cnt);
    for (register int i=1;i<=cnt;i++) printf("%d %d\n",ansl[i],ansr[i]);
    fclose(stdin);fclose(stdout);
}

原文地址:https://www.cnblogs.com/mastervan/p/9477989.html

时间: 2024-08-01 09:55:22

[线段树]JZOJ 5812的相关文章

[线段树] Jzoj P4231 寻找神格

Description 淬炼完神体,王仙女被传送到了遥远处一座没有神雷的浮岛上,发现浮岛上除了一扇门以外什么都没有.他来到门前,发现上面写着这样一段话:一个神出了拥有强大的神体外,还需要一枚神格.然而,想要获得神格没那么简单,除了有实力外还需要有运气.曾经有一个人叫金(jin)字(zi)塔(da),他的神体很强,很壮,可是他根本没有运气,所以最后神格拒绝了他.打开这扇门,你将会进入一个神格创造的空间,在那里,神格将会问你一些问题来测试你解决问题的能力,当然,它的问题将会很难,在你答不出来的时候你

[扫描线][线段树]JZOJ 4238 纪念碑

Description 2034年,纪念中学决定修建校庆100周年纪念碑,作为杰出校友的你被找了过来,帮校方确定纪念碑的选址.纪念中学的土地可以看作是一个长为n,宽为m的矩形.它由n* m个1*1的正方形组成,其中左下角的正方形的坐标为(1,1),右上角的正方形的坐标为(n, m).其中有一些土地已经被用来修建建筑物,每一幢建筑物都可以看做是一个左下角为(x1,y1),右上角为(x2,y2)的矩形.纪念碑可以看作是一个正方形.校方希望你找出一块最大的正方形区域供他们参考. Input 每一组数据

[线段树]JZOJ 1214 项链工厂

Description T 公司是一家专门生产彩色珠子项链的公司,其生产的项链设计新颖.款式多样.价格适中,广受青年人的喜爱.最近T 公司打算推出一款项链自助生产系统,使用该系统顾客可以自行设计心目中的美丽项链. 该项链自助生产系统包括硬件系统与软件系统,软件系统与用户进行交互并控制硬件系统,硬件系统接受软件系统的命令生产指定的项链.该系统的硬件系统已经完成,而软件系统尚未开发,T 公司的人找到了正在参加全国信息学竞赛的你,你能帮助T 公司编写一个软件模拟系统吗? 一条项链包含N 个珠子,每个珠

[扫描线][倍增][dfs序][线段树] Jzoj P6276 树

Description 有一棵n个节点的无根树,给出其中的m对点对<x,y>.问有多少条树上的简单路径<u,v>满足该路径上不存在任何一对给出的点对<x,y>. 这里我们认为路径<u,v>和<v,u>是相同的.并且对于题目中给出的点对<x,y>满足x!=y,对于你要计数的路径<u,v>满足u!=v(即单点不算答案). 题解 我们先把每个点在dfs上入队出队的时间给弄出来 然后可以转换为在平面上的n个矩阵 就可以用扫描线+线

[树上差分][线段树合并]JZOJ 3397 雨天的尾巴

Description 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连 根拔起,以及田地里的粮食被弄得一片狼藉. 无奈的深绘里和村民们只好等待救济粮来维生. 不过救济粮的发放方式很特别. 首先村落里的一共有n 座房屋,并形成一个树状结构.然后救济粮分m 次发放,每次选择 两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮.

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

bzoj1798: [Ahoi2009]Seq 维护序列seq 线段树

题目传送门 这道题就是线段树 先传乘法标记再传加法 #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int M=400010; LL read(){ LL ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击