2020牛客暑期多校训练营(第二场)HHappy Triangle线段树维护相邻两个元素的差

tech2024-07-13  69

思路比较简单,这题主要考验码力。

显然:分情况讨论:

1: a<b<x 时, ab尽量大

2:a<x<b时,a尽量大,b尽量小

3: x<a<b时,  b-a尽量小

1.2直接用set维护即可。

3用线段树维护,每次单点更新最多修改线段树2个点的值。

主要是细节问题。具体看代码。

 

#include <bits/stdc++.h> using namespace std; #define ls (o<<1) #define rs (o<<1|1) const int M = 2e5+7,inf = 2e9+7; int tr[M<<2],li[M],sz;multiset<int>s; void bd(int o,int l,int r)//初始化建树 { tr[o]=inf;if(l==r)return ; int m=(l+r)/2;bd(ls,l,m);bd(rs,m+1,r); } void up(int o,int l,int r,int x,int d)//单点赋值 { if(l==r) { tr[o]=d; return ; } int m=(l+r)/2; if(x<=m)up(ls,l,m,x,d); else up(rs,m+1,r,x,d); tr[o]=min(tr[ls],tr[rs]); } int qu(int o,int l,int r,int x,int y)//区间查询最小值 { if(x<=l&&r<=y)return tr[o]; int m=(l+r)/2,mn=inf; if(x<=m)mn=min(mn,qu(ls,l,m,x,y)); if(y>m)mn=min(mn,qu(rs,m+1,r,x,y)); return mn; } struct node{int op,x;}p[M]; int hs(int x){return lower_bound(li+1,li+1+sz,x)-li;} int main() { // freopen("8.in","r",stdin); int Q; scanf("%d",&Q); for(int i=1;i<=Q;i++) { scanf("%d%d",&p[i].op,&p[i].x); li[++sz]=p[i].x; } sort(li+1,li+1+sz); sz=unique(li+1,li+1+sz)-(li+1); //线段树维护1 ~ sz-1 表示第i+1个数与第i个数的差值 bd(1,1,sz); for(int i=1;i<=Q;i++) { int op=p[i].op,x=p[i].x; x=hs(x); auto nxt=s.upper_bound(x),pre=s.lower_bound(x); if(op==1) { if(s.count(x)==0)//每次插入最多只会改变x和 x的前驱。 因为线段树维护的是每个值与其后继的差值 { if(nxt!=s.end())up(1,1,sz,x,li[*nxt]-li[x]);//更新x else up(1,1,sz,x,inf); if(pre!=s.begin()) { --pre; if(s.count(*pre)==1)up(1,1,sz,*pre,li[x]-li[*pre]);//更新x得前驱 } } else up(1,1,sz,x,0);//权值x的数大于1,则只把权值x的后继减去x的权值更新为0,其余不变(因为我们要尽量求得权值差最小) s.insert(x); } else if(op==2) { if(s.count(x)==1)//这种情况下最多改变x与其前驱。 { up(1,1,sz,x,inf);//更新x ,x不存在,直接设为inf if(pre!=s.begin()) { --pre; if(s.count(*pre)==1)//大于1始终为0 { if(nxt!=s.end())up(1,1,sz,*pre,li[*nxt]-li[*pre]);//更新x得前驱 else up(1,1,sz,*pre,inf);//x的前驱的后继不存在,其线段树维护的值直接设为inf } } } else if(s.count(x)==2)//这种情况下,只会改变x的值,(如果x后继存在的话) { if(nxt!=s.end())up(1,1,sz,x,li[*nxt]-li[x]); else up(1,1,sz,x,inf); } //其余情况不会改变 s.erase(s.lower_bound(x)); } else { // for(auto x:s)cout<<li[x]<<" "; // cout<<endl; bool flag=false; if(pre!=s.begin()) { --pre;auto pre2=pre; if(pre2!=s.begin()) { --pre2; if(li[*pre]+li[*pre2]>li[x])flag=true; // cout<<"---- "<<li[*pre]<<" "<<li[*pre2]<<" "<<li[x]<<endl; } if(nxt!=s.end()&&li[*pre]+li[x]>li[*nxt])flag=true; } int mn=qu(1,1,sz,x,sz); if(mn<li[x])flag=true; // cout<<mn<<" "<<x<<endl; if(flag)puts("Yes"); else puts("No"); } } return 0; } /* 20 1 902364824 1 976541380 1 195794093 1 986278573 2 902364824 1 277734300 1 102939109 1 897242342 1 735343743 1 71002172 2 986278573 1 493686892 1 979151197 1 715139216 3 7496641 1 785130190 2 897242342 3 7535169 3 9808246 3 79704 */

 

最新回复(0)