最假女选手

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 480  Solved: 118
[Submit][Status][Discuss]

Description

在刚刚结束的水题嘉年华的压轴节目放水大赛中,wyywyy如愿以偿的得到了最假女选手的奖项。但是作为主办人的
C_SUNSHINE为了证明wyywyy确实在放水,决定出一道基础题考察wyywyy的姿势水平。给定一个长度为 N序列,编号
从1 到 N。要求支持下面几种操作:
1.给一个区间[L,R] 加上一个数x 
2.把一个区间[L,R] 里小于x 的数变成x 
3.把一个区间[L,R] 里大于x 的数变成x 
4.求区间[L,R] 的和
5.求区间[L,R] 的最大值
6.求区间[L,R] 的最小值

Input

第一行一个整数 N表示序列长度。
第二行N 个整数Ai 表示初始序列。
第三行一个整数M 表示操作个数。
接下来M 行,每行三或四个整数,第一个整数Tp 表示操作类型,接下来L,R,X 或L,R 表述操作数。
1<=tp<=6,N,M<=5*10^5,|Ai|<=10^8
Tp=1时,|x|<=1000
Tp=2或3时,|x|<=10^8

Output

对于每个4,5,6类型的操作输出一行一个整数表示答案。

Sample Input

2
1 2
2
2 1 2 2
4 1 2

Sample Output

4

HINT

 

题解:吉利线段树的模板题

https://pan.baidu.com/s/1o7xSSQ2

 #include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map> #define ll long long
#define inf 1000000007
#define N 500007
#define ls p<<1
#define rs p<<1|1
using namespace std;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m;
int mx[N<<],cx[N<<],sx[N<<];//区间最大值,最大值个数 ,区间严格次大值
int mn[N<<],cn[N<<],sn[N<<];//区间最小值,最小值个数 ,区间严格次小值
int add[N<<];//区间tag标记
ll sum[N<<];//区间和 inline void push_up(int p)
{
sum[p]=sum[ls]+sum[rs]; if (mx[ls]>mx[rs]) mx[p]=mx[ls],cx[p]=cx[ls],sx[p]=max(sx[ls],mx[rs]);
if (mx[ls]<mx[rs]) mx[p]=mx[rs],cx[p]=cx[rs],sx[p]=max(mx[ls],sx[rs]);
if (mx[ls]==mx[rs]) mx[p]=mx[ls],cx[p]=cx[ls]+cx[rs],sx[p]=max(sx[ls],sx[rs]); if (mn[ls]<mn[rs]) mn[p]=mn[ls],cn[p]=cn[ls],sn[p]=min(sn[ls],mn[rs]);
if (mn[ls]>mn[rs]) mn[p]=mn[rs],cn[p]=cn[rs],sn[p]=min(mn[ls],sn[rs]);
if (mn[ls]==mn[rs]) mn[p]=mn[ls],cn[p]=cn[ls]+cn[rs],sn[p]=min(sn[ls],sn[rs]);
// cout<<sum[p]<<endl;
}
inline void push_down(int p,int l,int r)
{
if (add[p])
{
int mid=(l+r)>>;
mx[ls]+=add[p],sx[ls]+=add[p],mn[ls]+=add[p],sn[ls]+=add[p],sum[ls]+=(mid-l+)*add[p],add[ls]+=add[p];
mx[rs]+=add[p],sx[rs]+=add[p],mn[rs]+=add[p],sn[rs]+=add[p],sum[rs]+=(r-mid)*add[p],add[rs]+=add[p];
add[p]=;
}
if (mx[ls]>mx[p])
{
if (mn[ls]==mx[ls]) mn[ls]=mx[p];
if (sn[ls]==mx[ls]) sn[ls]=mx[p];
sum[ls]+=1ll*(mx[p]-mx[ls])*cx[ls],mx[ls]=mx[p];
}
if (mx[rs]>mx[p])
{
if (mn[rs]==mx[rs]) mn[rs]=mx[p];
if (sn[rs]==mx[rs]) sn[rs]=mx[p];
sum[rs]+=1ll*(mx[p]-mx[rs])*cx[rs],mx[rs]=mx[p];
}
if (mn[ls]<mn[p])
{
if (mx[ls]==mn[ls]) mx[ls]=mn[p];
if (sx[ls]==mn[ls]) sx[ls]=mn[p];
sum[ls]+=1ll*(mn[p]-mn[ls])*cn[ls],mn[ls]=mn[p];
}
if (mn[rs]<mn[p])
{
if (mx[rs]==mn[rs]) mx[rs]=mn[p];
if (sx[rs]==mn[rs]) sx[rs]=mn[p];
sum[rs]+=1ll*(mn[p]-mn[rs])*cn[rs],mn[rs]=mn[p];
}
}
void build(int p,int l,int r)
{
if (l==r)
{
mx[p]=mn[p]=sum[p]=read();
cx[p]=cn[p]=;
sx[p]=-inf,sn[p]=inf;
return;
}
int mid=(l+r)>>;
build(ls,l,mid),build(rs,mid+,r);
push_up(p);
}
void vadd(int p,int l,int r,int x,int y,int z)
{
if (l==x&&y==r)
{
mx[p]+=z,sx[p]+=z,mn[p]+=z,sn[p]+=z;
sum[p]+=1ll*(r-l+)*z,add[p]+=z;
return;
}
push_down(p,l,r);
int mid=(l+r)>>;
if (y<=mid) vadd(ls,l,mid,x,y,z);
else if (x>mid) vadd(rs,mid+,r,x,y,z);
else vadd(ls,l,mid,x,mid,z),vadd(rs,mid+,r,mid+,y,z);
push_up(p);
}
void vmax(int p,int l,int r,int x,int y,int z)
{
//cout<<p<<" "<<l<<" "<<r<<" "<<x<<" "<<y<<" "<<z<<endl;
if (mn[p]>=z) return;
if (l==x&&y==r&&sn[p]>z)
{
//cout<<p<<" "<<l<<" "<<r<<endl;
if (mx[p]==mn[p]) mx[p]=z;
if (sx[p]==mn[p]) sx[p]=z;
sum[p]+=1ll*(z-mn[p])*cn[p],mn[p]=z;
return;
}
push_down(p,l,r);
int mid=(l+r)>>;
if (y<=mid) vmax(ls,l,mid,x,y,z);
else if (x>mid) vmax(rs,mid+,r,x,y,z);
else vmax(ls,l,mid,x,mid,z),vmax(rs,mid+,r,mid+,y,z);
push_up(p);
}
void vmin(int p,int l,int r,int x,int y,int z)
{
if (mx[p]<=z) return;
if (l==x&&y==r&&sx[p]<z)
{
//cout<<l<<" "<<r<<" "<<p<<endl;
if (mn[p]==mx[p]) mn[p]=z;
if (sn[p]==mx[p]) sn[p]=z;
sum[p]+=1ll*(z-mx[p])*cx[p],mx[p]=z;
// cout<<sum[p]<<" "<<l<<" "<<r<<" "<<p<<endl;
return;
}
push_down(p,l,r);
int mid=(l+r)>>;
if (y<=mid) vmin(ls,l,mid,x,y,z);
else if (x>mid) vmin(rs,mid+,r,x,y,z);
else vmin(ls,l,mid,x,mid,z),vmin(rs,mid+,r,mid+,y,z);
// cout<<l<<" "<<r<<" "<<sum[p]<<endl;
push_up(p);
// cout<<p<<" "<<l<<" "<<r<<" "<<sum[p]<<" "<<sum[ls]<<" "<<sum[rs]<<endl;
}
ll qsum(int p,int l,int r,int x,int y)
{
//cout<<l<<" "<<r<<" "<<p<<" "<<sum[p]<<endl;
if (l==x&&y==r) return sum[p];
push_down(p,l,r);
int mid=(l+r)>>;
if (y<=mid) return qsum(ls,l,mid,x,y);
else if (x>mid) return qsum(rs,mid+,r,x,y);
else return qsum(ls,l,mid,x,mid)+qsum(rs,mid+,r,mid+,y);
}
int qmax(int p,int l,int r,int x,int y)
{
if (l==x&&y==r) return mx[p];
push_down(p,l,r);
int mid=(l+r)>>;
if (y<=mid) return qmax(ls,l,mid,x,y);
else if (x>mid) return qmax(rs,mid+,r,x,y);
else return max(qmax(ls,l,mid,x,mid),qmax(rs,mid+,r,mid+,y));
}
int qmin(int p,int l,int r,int x,int y)
{
if (l==x&&y==r) return mn[p];
push_down(p,l,r);
int mid=(l+r)>>;
if (y<=mid) return qmin(ls,l,mid,x,y);
else if (x>mid) return qmin(rs,mid+,r,x,y);
else return min(qmin(ls,l,mid,x,mid),qmin(rs,mid+,r,mid+,y));
}
int main()
{
freopen("fzy.in","r",stdin);
freopen("fzy.out","w",stdout); n=read();
build(,,n);
m=read();
while(m--)
{
int opt=read(),x=read(),y=read(),z;
if (opt==) z=read(),vadd(,,n,x,y,z);
if (opt==) z=read(),vmax(,,n,x,y,z);
if (opt==) z=read(),vmin(,,n,x,y,z);
if (opt==) printf("%lld\n",qsum(,,n,x,y));
if (opt==) printf("%d\n",qmax(,,n,x,y));
if (opt==) printf("%d\n",qmin(,,n,x,y));
}
}

bzoj 4695 最假女选手 吉利线段树的更多相关文章

  1. BZOJ.4695.最假女选手(线段树 Segment tree Beats!)

    题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...

  2. BZOJ 4695 最假女选手 线段树

    题意: 给定一个长度为 N序列,编号从1 到 N.要求支持下面几种操作: 1.给一个区间[L,R] 加上一个数x  2.把一个区间[L,R] 里小于x 的数变成x  3.把一个区间[L,R] 里大于x ...

  3. bzoj 4695: 最假女选手 && Gorgeous Sequence HDU - 5306 && (bzoj5312 冒险 || 小B的序列) && bzoj4355: Play with sequence

    算导: 核算法 给每种操作一个摊还代价(是手工定义的),给数据结构中某些东西一个“信用”值(不是手动定义的,是被动产生的),摊还代价等于实际代价+信用变化量. 当实际代价小于摊还代价时,增加等于差额的 ...

  4. bzoj 4695: 最假女选手

    ……一道丧病线段树膜板题…… 被常数卡的死去活来……QAQ 学到了些奇技淫巧:把取min标记 和 区间最小值 合并 可以快很多…… #include <bits/stdc++.h> #de ...

  5. 2018.07.27 bzoj4695: 最假女选手(线段树)

    传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...

  6. (WC2016模拟十一)【BZOJ4695】最假女选手

    ps:好久没更博啦……这几天连着有模拟赛,等初赛前后休息的时候来疯狂补坑吧……顺便补一下前面的数论啥的? 题解: mdzz我场上写了个15分暴力长度跟标算差不多... 线段树大法好啊!这题听说很多人做 ...

  7. [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)

    [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...

  8. BZOJ4695 最假女选手(势能线段树)

    BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...

  9. 【bzoj4695】最假女选手 线段树区间最值操作

    题目描述 给定一个长度为 N 序列,编号从 1 到 N .要求支持下面几种操作:1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于 ...

随机推荐

  1. linux 命令行基础

    命令行基础 一些名词 「图形界面」 「命令行」 「终端」 「shell」 「bash」 安装使用 Windws: 安装git, 打开 gitbash Linux 打开终端 Mac 打开终端 基本命令 ...

  2. linux服务器操作小技巧

    python程序后台一直运行,并将打印信息输出到文件中 nohup -u test.py > out.txt & -u 表示无缓冲,直接将打印信息输出带文件中 &表示程序后台运行

  3. IntelliJ IDEA for MAC 注释模板、快捷键生成注释

    增加注释 在IntelliJ IDEA中为JAVA代码增加注释,首先需要配置注释模板,而后使用模板快捷键生成注释, 下面按照[配置模板].[模板使用]两部分进行介绍 ----------------- ...

  4. Linux 应用笔记

    Linux 应用笔记 Linux 应用笔记 小书匠 Raspberry Pi 常用命令 CentOs Raspberry Ubuntu python 实用教程 Vim 权限问题 内存分配 shell ...

  5. 基于spec评论“欢迎来怼”团队Alpha版作品

    “欢迎来怼”团队的作品是手机版博客园 1.获取此博客园app的方式——二维码 通过扫描二维码的方式下载app,这是当今比较流行的方式,适合广大手机的使用者——青少年的使用习惯. 2.点击图标,进入该a ...

  6. Spark GraphX 2

    顶点:VertexRDD   边:EdgeRDD.Edge.EdgeDirection   Triplet:EdgeTriplet   存储:PartitionStrategy 通常的存储方式有两种: ...

  7. jQuery对象和DOM对象使用说明

    1.jQuery对象和DOM对象第一次学习jQuery,经常分辨不清哪些是jQuery对象,哪些是 DOM对象,因此需要重点了解jQuery对象和DOM对象以及它们之间的关系.DOM对象,即是我们用传 ...

  8. 在c++中调用exe程序进行操作

    #include <Windows.h> #include <iostream> #include <direct.h> #define picNum 228 us ...

  9. python dict 字典

    字典是通过hash表的原理实现的,每个元素都是一个键值对,通过元素的键计算出一个唯一的哈希值,这个hash值决定了元素的地址,因此为了保证元素地址不一样,必须保证每个元素的键和对应的hash值是完全不 ...

  10. [Leetcode] 2.Add Two Numbers(List To Long,模拟)

    本题题意是指将两个数倒序存储在链表中,再将两数之和同样存储在链表中输出. 我最开始的思路是将每一位相加,再考虑是否进位,但这时就需要考虑一些情况,比较麻烦. 于是我决定采取另一种在网上新学到的方法:这 ...