• [HihoCoder1169]猜单词


    题目大意:
      给你一个数列,问区间[l,r]内与k最接近的数与k的差是多少。

    思路:
      将数列中的数和询问的数先从小到大排序,
      从小到大枚举每个数,如果是数列上的,就加到线段树中,
      如果是询问中的,就在线段树上查找区间最大值,
      这样就找到了区间中小于等于这个数的最大值。
      反过来也一样。
      一个最大值、一个最小值,对于询问的数作差,取min即可。
      比原来的主席树算法不知道妙到哪里去了。
      主席树加了离散化以后应该能过,不过我的程序一直没过,然而虞皓翔同样是主席树的程序可以随便过。
      大概是我写得比较烂吧。

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<vector>
      4 #include<algorithm>
      5 #include<functional>
      6 
      7 inline int getint() {
      8     register char ch;
      9     while(!isdigit(ch=getchar()));
     10     register int x=ch^'0';
     11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     12     return x;
     13 }
     14 
     15 const int inf=0x7fffffff;
     16 const int N=200001;
     17 
     18 struct Num {
     19     int val,pos,l,r,id;
     20     bool operator < (const Num &another) const {
     21         if(val<another.val) return true;
     22         if(val>another.val) return false;
     23         return pos;
     24     }
     25     bool operator > (const Num &another) const {
     26         if(val>another.val) return true;
     27         if(val<another.val) return false;
     28         return pos;
     29     }
     30 };
     31 std::vector<Num> v;
     32 
     33 class SegmentTree {
     34     #define _left <<1
     35     #define _right <<1|1
     36     private:
     37         int val[N<<2];
     38         void push_up(const int &p,const bool &cmp) {
     39             val[p]=cmp?std::max(val[p _left],val[p _right]):std::min(val[p _left],val[p _right]);
     40         }
     41     public:
     42         void reset(const int &x) {
     43             std::fill(&val[0],&val[N<<2],x);
     44         }
     45         void modify(const int &p,const int &b,const int &e,const int &x,const int &v,const bool &cmp) {
     46             if(b==e) {
     47                 val[p]=v;
     48                 return;
     49             }
     50             const int mid=(b+e)>>1;
     51             if(x<=mid) modify(p _left,b,mid,x,v,cmp);
     52             if(x>mid) modify(p _right,mid+1,e,x,v,cmp);
     53             push_up(p,cmp);
     54         }
     55         int query(const int &p,const int &b,const int &e,const int &l,const int &r,const bool &cmp) {
     56             if(b==l&&e==r) {
     57                 return val[p];
     58             }
     59             const int mid=(b+e)>>1;
     60             int ret=cmp?-1:inf;
     61             if(l<=mid) ret=cmp?std::max(ret,query(p _left,b,mid,l,std::min(mid,r),cmp)):std::min(ret,query(p _left,b,mid,l,std::min(mid,r),cmp));
     62             if(r>mid) ret=cmp?std::max(ret,query(p _right,mid+1,e,std::max(mid+1,l),r,cmp)):std::min(ret,query(p _right,mid+1,e,std::max(mid+1,l),r,cmp));
     63             return ret;
     64         }
     65     #undef _left
     66     #undef _right
     67 };
     68 SegmentTree t;
     69 
     70 int ans[N];
     71 
     72 int main() {
     73     int T=getint();
     74     for(register int i=1;i<=T;i++) {
     75         printf("Case #%d:
    ",i);
     76         const int n=getint(),q=getint();
     77         v.clear();
     78         for(register int i=1;i<=n;i++) {
     79             v.push_back((Num){getint(),i,0,0,0});
     80         }
     81         for(register int i=0;i<q;i++) {
     82             const int l=getint(),r=getint(),k=getint();
     83             v.push_back((Num){k,0,l,r,i});
     84         }
     85         std::fill(&ans[0],&ans[q],inf);
     86         t.reset(-1);
     87         std::sort(v.begin(),v.end(),std::less<Num>());
     88         for(register std::vector<Num>::iterator it=v.begin();it!=v.end();it++) {
     89             if(it->pos) {
     90                 t.modify(1,1,n,it->pos,it->val,true);
     91             } else {
     92                 const int tmp=t.query(1,1,n,it->l,it->r,true);
     93                 if(tmp!=-1) ans[it->id]=std::min(ans[it->id],std::abs(tmp-it->val));
     94             }
     95         }
     96         t.reset(inf);
     97         std::sort(v.begin(),v.end(),std::greater<Num>());
     98         for(register std::vector<Num>::iterator it=v.begin();it!=v.end();it++) {
     99             if(it->pos) {
    100                 t.modify(1,1,n,it->pos,it->val,false);
    101             } else {
    102                 const int tmp=t.query(1,1,n,it->l,it->r,false);
    103                 if(tmp!=inf) ans[it->id]=std::min(ans[it->id],std::abs(tmp-it->val));
    104             }
    105         }
    106         for(register int i=0;i<q;i++) {
    107             printf("%d
    ",ans[i]);
    108         }
    109     }
    110     return 0;
    111 }
    View Code

    原来也写过一个主席树的写法,然而复杂度不是很优秀,一直过不了。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int inf=0x7fffffff;
    12 const int N=200001;
    13 int size;
    14 class FotileTree {
    15     private:
    16         struct Node {
    17             int left,right,val;
    18         };
    19         Node nd[N*40];
    20         int sz,newNode(const int &p) {
    21             sz++;
    22             nd[sz]=nd[p];
    23             return sz;
    24         }
    25     public:
    26         int root[N];
    27         void reset() {
    28             sz=0;
    29         }
    30         int modify(const int &p,const int &b,const int &e,const int &x) {
    31             int new_p=newNode(p);
    32             nd[new_p].val++;
    33             if(b==e) return new_p;
    34             const int mid=(b+e)>>1;
    35             if(x<=mid) nd[new_p].left=modify(nd[p].left,b,mid,x);
    36             if(x>mid) nd[new_p].right=modify(nd[p].right,mid+1,e,x);
    37             return new_p;
    38         }
    39         int queryleq(const int &p1,const int &p2,const int &b,const int &e,const int &x) const {
    40             if(!(nd[p2].val-nd[p1].val)) return size-1;
    41             if(b==e) return e;
    42             const int mid=(b+e)>>1;
    43             if(x<=mid) return queryleq(nd[p1].left,nd[p2].left,b,mid,x);
    44             int ret;
    45             if((ret=queryleq(nd[p1].right,nd[p2].right,mid+1,e,x))!=size-1) return ret;
    46             if((ret=queryleq(nd[p1].left,nd[p2].left,b,mid,x))!=size-1) return ret;
    47             return size-1;
    48         }
    49         int querygeq(const int &p1,const int &p2,const int &b,const int &e,const int &x) const {
    50             if(!(nd[p2].val-nd[p1].val)) return size-1;
    51             if(b==e) return b;
    52             const int mid=(b+e)>>1;
    53             if(x>mid) return querygeq(nd[p1].right,nd[p2].right,mid+1,e,x);
    54             int ret;
    55             if((ret=querygeq(nd[p1].left,nd[p2].left,b,mid,x))!=size-1) return ret;
    56             if((ret=querygeq(nd[p1].right,nd[p2].right,mid+1,e,x))!=size-1) return ret;
    57             return size-1;
    58         }
    59 };
    60 FotileTree t;
    61 int a[N],l[N],r[N],x[N],b[N+N];
    62 int main() {
    63     int T=getint();
    64     for(register int i=1;i<=T;i++) {
    65         printf("Case #%d:
    ",i);
    66         const int n=getint(),q=getint();
    67         b[0]=inf;
    68         for(register int i=1;i<=n;i++) {
    69             b[i]=a[i]=getint();
    70         }
    71         for(register int i=1;i<=q;i++) {
    72             l[i]=getint();
    73             r[i]=getint();
    74             b[n+i]=x[i]=getint();
    75         }
    76         std::sort(&b[0],&b[n+q+1]);
    77         size=std::unique(&b[0],&b[n+q+1])-b;
    78         for(register int i=1;i<=n;i++) {
    79             const int id=std::lower_bound(&b[0],&b[size],a[i])-b;
    80             t.root[i]=t.modify(t.root[i-1],0,size-1,id);
    81         }
    82         for(register int i=1;i<=q;i++) {
    83             const int id=std::lower_bound(&b[0],&b[size],x[i])-b;
    84             const int leq=b[t.queryleq(t.root[l[i]-1],t.root[r[i]],0,size-1,id)];
    85             const int geq=b[t.querygeq(t.root[l[i]-1],t.root[r[i]],0,size-1,id)];
    86             printf("%d
    ",std::min(std::abs(x[i]-leq),std::abs(x[i]-geq)));
    87         }
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    Element Pagination分页组件 二次封装
    vue 发送短信验证码倒计时
    生成动态海报,带二维码
    H5九宫格抽奖,亲测可用
    elementui el-select使用远程搜索单选,输入内容不会触发remote-method
    日期格式转换,转换格式YYYY-MM-DD HH:mm:ss
    bignumber.js是一款用于任意精度十进制和非十进制算术的JavaScript库
    element table切换分页不勾选的自带方法
    密码强度校验
    webdriver-设置代理
  • 原文地址:https://www.cnblogs.com/skylee03/p/7644246.html
Copyright © 2020-2023  润新知