最假女选手

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. 【转】cocos2d工具汇总

    位图字体工具Bitmap Font Tools BMFont (Windows)FonteditorGlyph DesignerHieroLabelAtlasCreator 粒子编辑工具Particl ...

  2. 最小生成树(II)与Kruskal算法

    为防止网页加载过慢,故分两章.上接https://www.cnblogs.com/Uninstalllingyi/p/10479470.html Kruskal算法——将森林合并成树 玩过瘟疫公司吗… ...

  3. 90 [LeetCode] Subsets2

    Given a collection of integers that might contain duplicates, nums, return all possible subsets (the ...

  4. 【Machine Learning】如何处理机器学习中的非均衡数据集?

    在机器学习中,我们常常会遇到不均衡的数据集.比如癌症数据集中,癌症样本的数量可能远少于非癌症样本的数量:在银行的信用数据集中,按期还款的客户数量可能远大于违约客户的样本数量.   比如非常有名的德国信 ...

  5. maven 教程二 深入

    一:编写POM <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...

  6. 官方文档 恢复备份指南一 Introduction to Backup and Recovery

    1.备份分为:物理备份和逻辑备份    物理备份:备份数据文件  控制文件  归档日志文件     逻辑备份:EXP EXPDP备份等 物理备份为主,逻辑做补充     2.错误的类型         ...

  7. codeforces 303C. Minimum Modular(数论+暴力+剪枝+贪心)

    You have been given n distinct integers a1, a2, ..., an. You can remove at most k of them. Find the ...

  8. 迭代器类型:iterator & const_iterator

    vector<int> ivec{1, 3, 4, 1, 3, 4}; vector<int>::iterator iter; // iter能读写vector<int& ...

  9. MyBatis传入参数为list、数组、map写法(转载)

    MyBatis传入参数为list.数组.map写法 1.foreach简单介绍: foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合. foreach元素的属性主要有item ...

  10. Android中的回调Callback

    回调就是外部设置一个方法给一个对象, 这个对象可以执行外部设置的方法, 通常这个方法是定义在接口中的抽象方法, 外部设置的时候直接设置这个接口对象即可. 例如给安卓添加按钮点击事件, 我们创建了OnC ...