[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
原文地址:https://www.cnblogs.com/skylee03/p/7644246.html