找出第二大
时间限制:
4000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
给你n个数,然后询问你m次。每次询问只有两种情况:
Q L R : 输出 L 到 R 区间内第二大的值(与第一大的值相同的不算第二大)如果没有第二大的值,输出-1
S L R K : L 到 R 区间内,每个值减去 K-
输入
-
第1行输入n,m. 0<n,m,<=100000
第2行是n个整数ai, -1000000<=ai<=1000000
第3到第m+2,每行一个对应的操作。1<=l<=r<=n。 -1000000<=k<=1000000
输出
- 对于每个Q操作,输出答案。保证所有数据在int范围内(那为什么还把值弄得那么大呢?(~ ̄▽ ̄)~) 样例输入
-
5 6 1 1 1 2 3 Q 1 3 Q 4 5 Q 4 4 S 1 1 1 Q 1 3 Q 1 5
样例输出
-
-12-102
来源
- cszdlt 上传者
如过是找出最大的就是用线段树写,找出第二的也是可以用线段树写, 每个节点存两个值一个为最大值 ,一个为次大值,这样父亲节点的最大值就是左右两个儿子较大的那个,次大值就是左右两个儿子 最大的和次大的4 个数中不同于最大值的那个值。
#include<bits/stdc++.h> using namespace std; const int N = 100010; const int ing = 0x3f3f3f3f; const int inf = -ing; int ma[N<<2]; int mx[N<<2]; int add[N<<2]; int a[N]; bool cmp(int f ,int g) { return f>g; } void push_up(int rt) { ma[rt] = max(ma[rt<<1],ma[rt<<1|1]); int t[10]; t[1] = ma[rt<<1]; t[2] = ma[rt<<1|1]; t[3] = mx[rt<<1]; t[4] = mx[rt<<1|1]; mx[rt] = inf; if(t[1]>t[2]) { mx[rt] = t[2]; mx[rt] = max(t[3],mx[rt]); } else if(t[1]<t[2]) { mx[rt] = t[1]; mx[rt] = max(mx[rt],t[4]); } else { if(t[3]!=t[4]) { mx[rt] = max(t[3],t[4]); } else { if(t[3]!=t[1]) { mx[rt] = t[3]; } } } } int max(int a,int b) { return a>b?a:b; } void push_down(int rt) { if(add[rt]!=0) { add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; ma[rt<<1]+=add[rt]; ma[rt<<1|1]+=add[rt]; if(mx[rt<<1]!=inf) mx[rt<<1]+=add[rt]; if(mx[rt<<1|1]!=inf) mx[rt<<1|1]+=add[rt]; add[rt] = 0; } } void update(int L,int R,int l,int r,int rt,int k) { if(L<=l&&r<=R) { if(mx[rt]!=inf) mx[rt]+=k; ma[rt]+=k; add[rt]+=k; return; } push_down(rt); int mid = (l+r)>>1; if(L<=mid) update(L,R,l,mid,rt<<1,k); if(R>mid) update(L,R,mid+1,r,rt<<1|1,k); push_up(rt); } int query1(int L ,int R ,int l ,int r ,int rt) { if(L<=l&&r<=R) { return ma[rt]; } push_down(rt); int mid = (l+r)>>1; int k = inf; int g = inf; if(L<=mid) k = query1(L ,R ,l ,mid,rt<<1); if(R>mid) g = query1(L ,R ,mid+1,r, rt<<1|1); return max (k,g); } int query(int L ,int R ,int l ,int r ,int rt) { if(L<=l&&r<=R) { return mx[rt]; } push_down(rt); int w[5]; for(int i = 1 ; i<=4; i++) w[i] = inf; int mid = (l+r)>>1; int fg = inf; int ans = inf; if(L<=mid) { w[3] = query1(L ,R ,l ,mid,rt<<1); fg = max(fg,w[3]); } if(R>mid) { w[4] = query1(L ,R ,mid+1,r,rt<<1|1); fg = max(fg,w[4]); } if(w[3]!=fg) ans = max(ans,w[3]); if(w[4]!=fg) ans = max(ans,w[4]); if(L<=mid) { w[1] =query(L ,R,l ,mid,rt<<1); if(w[1]!=fg) ans= max(ans,w[1]); } if(R>mid) { w[2] = query(L ,R, mid+1,r,rt<<1|1); if(w[2]!=fg) ans = max(ans,w[2]); } return ans; } void bulid(int l,int r,int rt) { if(l==r) { scanf("%d",&a[l]); ma[rt] = a[l]; mx[rt] = inf; add[rt] = 0; return ; } add[rt] = 0; int mid = (l+r)>>1; bulid(l,mid,rt<<1); bulid(mid+1,r,rt<<1|1); push_up(rt); } char s[10]; int main() { int n, m; while(scanf("%d%d",&n,&m)!=EOF) { bulid(1,n,1); for(int i = 1; i<=m; i++) { scanf("%s",&s); int L ,R; int k; if(s[0]=='S') { scanf("%d%d%d",&L,&R,&k); update(L,R,1,n,1,-k); } else { scanf("%d%d",&L,&R); int kg = query(L ,R ,1 ,n ,1); if(kg ==inf) printf("-1\n"); else printf("%d\n",kg); } } } return 0; }
-
第1行输入n,m. 0<n,m,<=100000