zoukankan      html  css  js  c++  java
  • 2020牛客多校训练赛(第二场)补题

    比赛入口 

    H-Happy Triangle

    题意:

      有一个multiset  s,一共有三种操作:

      1.  s插入一个x;

      2.  s删除一个x;

      3.  查询s中是否存在两个数字,使得这两个数字能和x组成一个非退化三角形;

    思路:

      显然,s是有序的,且判断x是否能和s中两个数字组成非退化三角形,一共有以下三种情况:

      1. x是最大边,判断<=x的最后两个字;

      2. x是第二大边,判断>=x的第一个数字和<x的最后一个数字;

      3. x是最小边,判断比x大的任意两个数字的差值的绝对值小于x,由于s可视作有序,那么最优的方法就是从相邻的数字中找。

          这里可以用权值线段树来维护差值(下一个数字 - 当前数字),由于x∈[1,1e9] ,因此可以采取离线+离散化的做法。每次查询最小的差值即可。

      1 #include<bits/stdc++.h>
      2 /*
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<vector>
      7 #include<cctype>
      8 #include<queue>
      9 #include<algorithm>
     10 #include<map>
     11 #include<set>
     12 */
     13 #pragma GCC optimize(2)
     14 using namespace std;
     15 typedef long long LL;
     16 typedef unsigned long long uLL;
     17 typedef pair<int,int> pii;
     18 typedef pair<LL,LL> pLL;
     19 typedef pair<double,double> pdd;
     20 const int N=2e6+5;
     21 const int M=1e4+5;
     22 const int inf=2e9+5;
     23 const LL mod=1e9+7;
     24 const double eps=1e-5;
     25 const long double pi=acos(-1.0L);
     26 #define ls (i<<1)
     27 #define rs (i<<1|1)
     28 #define fi first
     29 #define se second
     30 #define pb push_back
     31 #define mk make_pair
     32 #define mem(a,b) memset(a,b,sizeof(a))
     33 LL read()
     34 {
     35     LL x=0,t=1;
     36     char ch;
     37     while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
     38     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
     39     return x*t;
     40 }
     41 multiset<int> s;//权值线段树维护下一个数字和当前数字的差值
     42 int c[N<<2],t[N],op[N],a[N],cnt[N],q,len;
     43 inline int getid(int x)
     44 {
     45     return lower_bound(t+1,t+len+1,x)-t;
     46 }
     47 void build(int i,int l,int r)
     48 {
     49     c[i]=inf;
     50     if(l==r) return;
     51     int mid=l+r>>1;
     52     build(ls,l,mid);
     53     build(rs,mid+1,r);
     54 }
     55 void update(int i,int l,int r,int pos,int x)
     56 {
     57     if(l==r)
     58     {
     59         c[i]=x;
     60         return ;
     61     }
     62     int mid=l+r>>1;
     63     if(pos<=mid) update(ls,l,mid,pos,x);
     64     else update(rs,mid+1,r,pos,x);
     65     c[i]=min(c[ls],c[rs]);
     66 }
     67 
     68 int query(int i,int l,int r,int ll,int rr)
     69 {
     70     if(ll<=l&&r<=rr) return c[i];
     71     int mid=l+r>>1,t1=inf,t2=inf;
     72     if(mid>=ll) t1=query(ls,l,mid,ll,rr);
     73     if(mid<rr) t2=query(rs,mid+1,r,ll,rr);
     74     return min(t1,t2);
     75 }
     76 int main()
     77 {
     78     s.insert(-1); //加入"人工"边界
     79     s.insert(-1);
     80     s.insert(inf);
     81     q=read();
     82     for(int i=1;i<=q;i++) op[i]=read(),t[i]=a[i]=read();
     83     sort(t+1,t+q+1);
     84     len=unique(t+1,t+q+1)-t-1;
     85     build(1,1,len);
     86     for(int i=1;i<=q;i++)
     87     {
     88         if(op[i]==1)
     89         {
     90             s.insert(a[i]);
     91             int x=getid(a[i]);
     92             cnt[x]++;
     93             if(cnt[x]==1)//新加入一种数字(一个数值对应一种,一个数值也对应离散化后的一个点)
     94             {
     95                 update(1,1,len,x,*s.upper_bound(a[i])-a[i]);
     96                 auto it=s.lower_bound(a[i]);
     97                 it--;
     98                 int tmp=*it;
     99                 int y=getid(tmp);
    100                 if(cnt[y]==1) update(1,1,len,y,a[i]-tmp);//如果上一个数字只有一个才更新(如果是两个,那么差值就是0了)
    101             }
    102             else if(cnt[x]==2) update(1,1,len,x,0);//同一种数字有两个
    103         }
    104         else if(op[i]==2)
    105         {
    106             s.erase(s.find(a[i]));
    107             int x=getid(a[i]);
    108             cnt[x]--;
    109             if(cnt[x]==1) update(1,1,len,x,*s.upper_bound(a[i])-a[i]); //从两个变成一个,那么最小差值0 被更新
    110             else if(cnt[x]==0)
    111             {
    112                 update(1,1,len,x,inf);
    113                 auto it=s.lower_bound(a[i]);
    114                 it--;
    115                 int tmp=*it;
    116                 int y=getid(tmp);
    117                 if(cnt[y]==1) update(1,1,len,y,*s.lower_bound(a[i])-tmp); //这种数字变为0个,当上一个数字只有一个时更新
    118             }
    119         }
    120         else
    121         {
    122             int flag=0;
    123             auto it=s.lower_bound(a[i]);
    124             int t1=*it;
    125             int t2=*(--it);
    126             int t3=*(--it);
    127            // printf("...%d %d %d
    ",t1,t2,t3);
    128             if(a[i]+t2>t1||t2+t3>a[i]) flag=1;//判断第一种情况和第二种情况
    129             if(query(1,1,len,getid(a[i]),len)<a[i] ) flag=1;//判断第三种情况
    130             if(flag) printf("Yes
    ");
    131             else printf("No
    ");
    132         }
    133     }
    134     return 0;
    135 }
    136 /*
    137 2
    138 1 1000000000
    139 3 1000000001
    140 
    141 6
    142 1 2
    143 1 2
    144 2 2
    145 3 3
    146 1 4
    147 3 5
    148 
    149 7
    150 1 3
    151 1 2
    152 1 100
    153 3 99
    154 3 1
    155 1 100
    156 3 1
    157 */
    H
  • 相关阅读:
    寒江独钓(0):内核开发上机指导
    异常:Hibernate数据库恢复错误
    天书夜读:从汇编语言到Windows内核编程笔记(4)
    企业WEBGIS网站解决方案
    如何使用国际开源项目构建一个完整的GIS(地理信息)应用系统
    将指定文件夹下的所有文件copy到目标文件夹下
    一些jquery的小知识
    压缩指定目录下指定文件(包括子目录下的文件)
    解压一个rar文件
    关于下载txt文本文挡的问题
  • 原文地址:https://www.cnblogs.com/DeepJay/p/13296311.html
Copyright © 2011-2022 走看看