Description

题目背景

   热烈庆祝北京师范大学附属实验中学成立100周年!

问题描述

   校庆筹备组的老师们正在寻找合适的地方来举办校庆庆典。学生们的位置和可以举办庆典的位置在x轴的正半轴取值在[1,n]的整数位置上。老师们选择的地点是会根据参加典礼的学生位置来决定的,具体来说:定义一个位置的距离和为该位置到所有参加学生的距离之和。如果一个位置的距离和最小,且它比所有和它距离和相等的位置的位置更靠左,则老师们会选择这个位置。开始时,所有的位置都可以举办庆典。但很可惜的是,并不是所有的位置都能举办庆典,有些奇怪的事件会使[l,r]这段区间不能举办庆典,不过有时也会使[l,r]可以重新举办庆典(并不保证[l,r]之前的每个位置都不能举办庆典)。有时一些学生会因为某些原因不能参加庆典,有时一些学生会主动报名参加庆典。作为一名合格的老师,你需要求出每个事件发生后庆典应该选择的位置,如果没有合法位置,请输出-1。

Input

第一行包含两个整数n,q,表示坐标的范围和发生事件的个数。
第二行包含n个整数,第i个整数ai表示在初始时刻每个位置上的学生数量。
接下来q行每行先有一个整数type。
若type=1,接下来有两个整数x,k,表示在x位置增加k名学生。
若type=2,接下来有两个整数x,k,表示在x位置减少k名学生,保证x位置一定存在至少k名学生。
若type=3,接下来有两个整数l,r,表示在[l,r]这段区间可以重新举办庆典。
若type=4,接下来有两个整数l,r,表示在[l,r]这段区间不再能举办庆典。

Output

输出总共q行,第i行的数为第i个事件发生后的答案。

Sample Input

5 4
1 0 1 0 0
1 4 1
2 3 1
4 1 3
3 2 3

Sample Output

3
1
4
2

样例说明

总共5个位置可以选择
第1个事件发生,新增加一名学生在4号位置。
第2个事件发生以前,学生分别在1,3,4位置,可以证明,在3的位置距离和最小且它是最靠左的那一个。
第2个事件发生,减少一名在3位置的学生。
第3个事件发生以前,学生分别在1,4位置,可以证明,在1的位置距离和最小且它是最靠左的那一个。
第3个事件发生,1到3号位置不能举办庆典。
第4个事件发生以前,学生分别在1,4位置,且1到3号位置不能举办庆典,可以证明,在4的位置距离和最小且它是最靠左的那一个。
第4个事件发生,2到3号位置能重新举办庆典。
最后,学生分别在1,4位置,且1号位置不能举办庆典,可以证明,在2的位置距离和最小且它是最靠左的那一个。

Data Constraint

对于20%的数据满足,n ≤ 200, q ≤ 200
对于50%的数据满足,n ≤ 2000, q ≤ 2000
对于另30%的数据满足,不存在type = 3和type = 4的操作。
对于100%的数据满足,1 ≤ n ≤ 2 ∗ 10^5, 1 ≤ q ≤ 2 ∗ 10^5, 1 ≤ k ≤ 2 ∗ 10^5, 0 ≤ ai ≤ 2 ∗ 10^5。

Solution

  • 首先我们要知道庆典肯定是在中位数处举办最好。

  • 如果一个位置已经不能举办了,那么一定是在这个位置左右最近的能举办的两个位置中其中一个。

  • 题述的四种操作都可以用线段树维护。

  • 之后二分一个位置查询这个点 xx 是否为中位数(区间查询两边人数)。

  • 若单点查询 xx 发现能举办,则直接输出。

  • 若不能举办,就区间查找 xx 两边最近的点:

  • 具体就是区间中维护 l,rl,r ,表示一个区间中能够达到的最近的点。

  • 再区间查询 (1,x−1)(1,x-1) 的 rr 和 (x+1,n)(x+1,n) 的 ll 即可。

  • 那么如何判断这两个点哪个更优呢?

  • 在线段树中维护 a[i]a[i] 和 a[i]∗ia[i]*i ,那么前半部分答案即为:a[i]∗x−a[i]∗ia[i]*x-a[i]*i

  • 后半部分取相反数即可,这样就能统计出一个点作为举办位置的答案。

  • 这样的时间复杂度就是大常数的 O(N log N)O(N\ log\ N) 。

Code

#include<cstdio>
using namespace std;
const int N=2e5+2;
int n;
long long a[N];
long long num;
template<typename T>T Max(T x,T y)
{return x>y?x:y;
}
template<typename T>T Min(T x,T y)
{return x<y?x:y;
}
struct Stream
{inline int read(){int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w;}inline void write(int x){if(x>9) write(x/10);putchar(x%10+'0');}inline void writeln(int x){if(x<0) x=-x,putchar('-');write(x),putchar('\n');}
}Std;
struct Segment_Tree
{struct data{int l,r,c;long long num,sum;bool bz;}f[N<<3];inline void update(int v){int ls=v<<1,rs=ls|1;f[v].num=f[ls].num+f[rs].num;f[v].sum=f[ls].sum+f[rs].sum;f[v].bz=f[ls].bz|f[rs].bz;if(f[ls].bz) f[v].l=f[ls].l; elseif(f[rs].bz) f[v].l=f[rs].l; else f[v].l=n+1;if(f[rs].bz) f[v].r=f[rs].r; elseif(f[ls].bz) f[v].r=f[ls].r; else f[v].r=-1;}inline void modify(int v,int l,int r){int ls=v<<1,rs=ls|1;if(f[v].c==1){f[v].c=0;f[ls].c=f[rs].c=1;f[ls].bz=f[rs].bz=true;f[ls].l=l,f[rs].r=r;int mid=(l+r)>>1;f[ls].r=mid,f[rs].l=mid+1;}elseif(f[v].c==2){f[v].c=0;f[ls].c=f[rs].c=2;f[ls].bz=f[rs].bz=false;f[ls].l=f[rs].l=n+1;f[ls].r=f[rs].r=-1;}}inline void make(int v,int l,int r){if(l==r){f[v].l=f[v].r=l;f[v].num=a[l];f[v].sum=a[l]*l;f[v].bz=true;return;}int mid=(l+r)>>1;make(v<<1,l,mid);make(v<<1|1,mid+1,r);update(v);}inline void change_num(int v,int l,int r,int x,int y){if(l==r){f[v].num+=y;f[v].sum+=(long long)y*l;return;}modify(v,l,r);int mid=(l+r)>>1;if(x<=mid) change_num(v<<1,l,mid,x,y); else change_num(v<<1|1,mid+1,r,x,y);update(v);}inline void change_bz(int v,int l,int r,int x,int y,bool z){if(l==x && r==y){f[v].bz=z;if(z) f[v].c=1; else f[v].c=2;if(!z) f[v].l=n+1,f[v].r=-1; else f[v].l=l,f[v].r=r;return;}modify(v,l,r);int mid=(l+r)>>1;if(y<=mid) change_bz(v<<1,l,mid,x,y,z); elseif(x>mid) change_bz(v<<1|1,mid+1,r,x,y,z); else{change_bz(v<<1,l,mid,x,mid,z);change_bz(v<<1|1,mid+1,r,mid+1,y,z);}update(v);}inline long long find_num(int v,int l,int r,int x,int y){if(l>=x && r<=y) return f[v].num;int mid=(l+r)>>1;if(y<=mid) return find_num(v<<1,l,mid,x,y);if(x>mid) return find_num(v<<1|1,mid+1,r,x,y);return find_num(v<<1,l,mid,x,mid)+find_num(v<<1|1,mid+1,r,mid+1,y);}inline long long find_sum(int v,int l,int r,int x,int y){if(l>=x && r<=y) return f[v].sum;int mid=(l+r)>>1;if(y<=mid) return find_sum(v<<1,l,mid,x,y);if(x>mid) return find_sum(v<<1|1,mid+1,r,x,y);return find_sum(v<<1,l,mid,x,mid)+find_sum(v<<1|1,mid+1,r,mid+1,y);}inline bool find_bz(int v,int l,int r,int x){modify(v,l,r);if(l==r) return f[v].bz;int mid=(l+r)>>1;bool bz=x<=mid?find_bz(v<<1,l,mid,x):find_bz(v<<1|1,mid+1,r,x);update(v);return bz;}inline int findl(int v,int l,int r,int x,int y){modify(v,l,r);if(l>=x && r<=y){if(!f[v].bz) return -1;return f[v].r;}int mid=(l+r)>>1;if(y<=mid) return findl(v<<1,l,mid,x,y);if(x>mid) return findl(v<<1|1,mid+1,r,x,y);return Max<int>(findl(v<<1,l,mid,x,mid),findl(v<<1|1,mid+1,r,mid+1,y));}inline int findr(int v,int l,int r,int x,int y){modify(v,l,r);if(l>=x && r<=y){if(!f[v].bz) return n+1;return f[v].l;}int mid=(l+r)>>1;if(y<=mid) return findr(v<<1,l,mid,x,y);if(x>mid) return findr(v<<1|1,mid+1,r,x,y);return Min<int>(findr(v<<1,l,mid,x,mid),findr(v<<1|1,mid+1,r,mid+1,y));}inline long long calc(int x){long long y=0;if(x>1) y=find_num(1,1,n,1,x-1)*x-find_sum(1,1,n,1,x-1);if(x<n) y+=find_sum(1,1,n,x+1,n)-find_num(1,1,n,x+1,n)*x;return y;}
}Tree;
int main()
{n=Std.read();int q=Std.read();for(int i=1;i<=n;i++) num+=a[i]=Std.read();Tree.make(1,1,n);while(q--){int type=Std.read(),x=Std.read(),y=Std.read();if(type==1) Tree.change_num(1,1,n,x,y),num+=y;if(type==2) Tree.change_num(1,1,n,x,-y),num-=y;if(type==3) Tree.change_bz(1,1,n,x,y,true);if(type==4) Tree.change_bz(1,1,n,x,y,false);int l=1,r=n,ans=0;long long sl=0,sr=0,midnum=(num+1)>>1;while(l<=r){int mid=(l+r)>>1;long long z=Tree.find_num(1,1,n,l,mid);if(sl+z<midnum) ans=mid,l=mid+1,sl+=z; else r=mid-1,sr+=num-sr-sl-z;}if(Tree.find_bz(1,1,n,++ans)){Std.writeln(ans);continue;}int ans1=ans>1?Tree.findl(1,1,n,1,ans-1):-1;int ans2=ans<n?Tree.findr(1,1,n,ans+1,n):n+1;if((ans1<0 || ans1>n) && (ans2<0 || ans2>n)){Std.writeln(-1);continue;}int node=ans1;if((ans1<0 || ans1>n) || ans2>0 && ans2<=n && Tree.calc(ans1)>Tree.calc(ans2)) node=ans2;Std.writeln(node);}return 0;
}

JZOJ 5419. 【NOIP2017提高A组集训10.24】筹备计划相关推荐

  1. JZOJ 5417. 【NOIP2017提高A组集训10.24】方阵

    Description 题目背景 热烈庆祝北京师范大学附属实验中学成立100周年! 问题描述 为了准备校庆庆典,学校招募了一些学生组成了一个方阵,准备在庆典上演出. 这个方阵是一个n*m的矩形,第i行 ...

  2. JZOJ 5438. 【NOIP2017提高A组集训10.31】Tree

    Description Input Output Sample Input 10 1 1 0 0 1 0 0 0 0 0 1 2 2 3 2 4 4 5 2 6 6 7 7 8 7 9 4 10 Sa ...

  3. JZOJ 5439. 【NOIP2017提高A组集训10.31】Calculate

    Description Input Output Data Constraint Solution 设前缀和 g[i][j]g[i][j] 表示 AA 为 ii .BB%A 为 jj 的数量. 这样就 ...

  4. JZOJ 5436. 【NOIP2017提高A组集训10.30】Group

    Description Input Output Sample Input 10 113 28 3 39 90 46 14 55 35 48 47 Sample Output 62453 Data C ...

  5. JZOJ 5431. 【NOIP2017提高A组集训10.28】序列操作

    Description 一开始有n个非负整数hi,接下来会进行m次操作,第i次操作给出一个数c[i],要求你选出c[i]个大于零的数并将它们减去1. 问最多可以进行多少轮操作后无法操作(即没有c[i] ...

  6. JZOJ 5426. 【NOIP2017提高A组集训10.25】摘Galo

    Description 0v0在野外看到了一棵Galo树,看到食物的0v0瞪大了眼睛,变成了OvO. 这棵Galo树可以看做是一棵以1号点为根的n个点的有根数,除了根节点以外,每个节点i都有一个Gal ...

  7. JZOJ 5421. 【NOIP2017提高A组集训10.25】嘟嘟噜

    Description 由于众所周知的原因, 冈部一直欠真由理一串香蕉. 为了封上真由理的嘴, 冈部承诺只要真由理回答出这个问题, 就给她买一车的香蕉: 一开始有n 个人围成一个圈, 从1 开始顺时针 ...

  8. JZOJ 5425. 【NOIP2017提高A组集训10.25】数论

    Description 聪明的0v0正在学习莫比乌斯反演. 她看到了这样的一道题:有n*m个人站成了一个n*m的方阵-- 剩下的题面,聪明的0v0不记得了.但是,她通过自己高超的数论技巧,给出了一个转 ...

  9. JZOJ 5422. 【NOIP2017提高A组集训10.25】天才绅士少女助手克里斯蒂娜

    Description Input 第一行两个整数n;m 表示电子个数和询问个数. 接下来n 行, 每行两个整数x; y 表示vi. 接下来m 行, 每行形如1 p x y 或2 l r, 分别表示两 ...

最新文章

  1. python 函数调用列表_在项目列表上调用一个函数的最简洁方法 - python
  2. #mysql50#_#mysql50#.ssh设个啥数据库?
  3. nginx启动只有master没有worker_深入浅出Nginx
  4. return 语句不可返回指向“栈内存”的“指针”
  5. 【NLP】GloVe的Python实现
  6. java 无类名实现接口_为什么很多人写 Java/Android 时,选择让同一个类实现多个接口,而不是用多个内部匿名类?...
  7. matplotlib(六)三维作图
  8. Emmet使用-----HTML
  9. Android开发之引用三方库导致SO库冲突的解决办法
  10. [原]排错实战——使用process explorer替换任务管理器
  11. (36)FPGA原语设计(BUFIO)
  12. python对蓝牙串口库_python对串口蓝牙模块的操作
  13. Linux系统版本大全
  14. 网站安全检测漏洞扫描系统邮件安全
  15. 输入成绩等级c语言,C语言实现学生成绩等级划分的方法实例
  16. 小程序支持HTML标签
  17. 如何规避Adobe Flash Player中重橙网络的广告弹窗
  18. STM8L151 DAC
  19. ismobile什么意思_英语mobile是什么中文意思
  20. java field_java中的field什么意思

热门文章

  1. Python学习:模块
  2. 高性能计算的线程模型:Pthreads 还是 OpenMP
  3. linux命令详解:md5sum命令
  4. mysql 优化300例_PHP+MySQL实现对一段时间内每天数据统计优化操作实例
  5. Softmax vs. SoftmaxWithLoss 推导过程
  6. [云炬创业基础笔记]第五章创业计划评估17
  7. 学长毕业日记 :本科毕业论文写成博士论文的神操作20170410
  8. 吐血整理!这可能是最全的机器学习工具手册
  9. SegNet 语义分割网络以及其变体 基于贝叶斯后验推断的 SegNet
  10. MySQL数据库中导入导出方法以及工具介绍