【解题报告】编程之美复赛 ——猜数字

题目连接:http://hihocoder.com/contest/msbop2015round3/problem/2

大意:给定一个数组,然后有多个查询(l,r,x)求在l~r区间内和x最小的差。

线段树维护。。。离线操作

先假定要求的是区间内比x小的数的最小差。那么我们可以从小到大逐个向线段树里面添加数组的值,然后从小到大查询每个查询的结果。

如:

数组:[1 8 3 4 9 2 7 6 5] 查询:[(1 9 10)、(3 7 9)、(5 6 5)]

逐个向线段树里面添加值。

初始化是0,

逐个添加1,2,3,4,5

变成[1,0,3,4,0,2,0,0,5] 这时候执行查询(5,6,5)。线段树维护的是区间最大值。那么这样查询出的结果就是2。也就是说区间5~6内比5小且最大的数是2。取绝对值就是3了。

离线操作也就是预先读取出全部的查询,按x排序,然后在添加的过程中逐个求出(不是按原来的顺序求),最后再根据输入的顺序输出全部的查询结果。

 

以同样的方法可以求出比x大且最小的数。取绝对值再和之前的结果求较小值就是题目要求的查询的结果了。

  1 /*l~r的节点的左孩子是l~(l+r)/2,右孩子是(l+r)/2+1~r*/
  2 #include<stdio.h>
  3 #include<algorithm>
  4 using namespace std;
  5 #define MAXLEN 1500000
  6 typedef int SaveData;/*节点内的储存数据*/
  7 typedef int Point;/*端点下标*/
  8 typedef struct node
  9 {
 10     Point l,r;/*左右端点*/
 11     SaveData value;/*值,如保存和,最值等等*/
 12     /*struct node *pl,*pr; /*链式情况下左右节点指标*/
 13 }SeTree;
 14 SeTree tree[MAXLEN]={0};
 15 SaveData ans;/*返回查询结果*/
 16 /*初始化线段树*/
 17 void bulid(Point v,Point l,Point r)
 18 {
 19     tree[v].l=l;
 20     tree[v].r=r;
 21     if(l==r)
 22     {
 23         tree[v].value=-999999999;
 24         //scanf("%ld",&tree[v].value);
 25         return ;
 26     }
 27     Point mid=(l+r)/2;
 28     bulid(v*2,l,mid);
 29     bulid(v*2+1,mid+1,r);
 30     tree[v].value=max(tree[v*2].value,tree[v*2+1].value);
 31 }
 32 /*更新区间l~r = m*/
 33 SaveData update(Point v,Point l,Point r,SaveData m)
 34 {
 35     SaveData s;
 36     if(tree[v].l==l&&tree[v].r==r)
 37     {
 38         tree[v].value=m;
 39         return m;
 40     }
 41     int mid=(tree[v].l+tree[v].r)/2;
 42     if(r<=mid) {s=update(v*2,l,r,m);}
 43     else
 44     {
 45         if(l>mid) update(v*2+1,l,r,m);
 46         else
 47         {
 48             update(v*2,l,mid,m);
 49             update(v*2+1,mid+1,r,m);
 50         }
 51     }
 52     tree[v].value=max(tree[v*2].value,tree[v*2+1].value);
 53     return s;
 54 }
 55 /*查询l~r*/
 56 void query(Point v,Point l,Point r)
 57 {
 58     if(tree[v].l==l&&tree[v].r==r)
 59     {
 60         ans=max(tree[v].value,ans);/*ans为全局变量*/
 61         return ;
 62     }
 63     int mid=(tree[v].l+tree[v].r)/2;
 64     if(r<=mid)query(v*2,l,r);
 65     else
 66     {
 67         if(l>mid) query(v*2+1,l,r);
 68         else
 69         {
 70             query(v*2,l,mid);
 71             query(v*2+1,mid+1,r);
 72         }
 73     }
 74 }
 75 pair<int,int> sc[200005];
 76 pair<int,pair<pair<int,int>,int> > q[200005];
 77 int ansans[200005];
 78 int t,n,qnum,i,j;
 79 const int INF=1000000000;
 80 int go()
 81 {
 82     bulid(1,1,n);
 83     i=n-1;j=qnum-1;
 84     while(i>=-1&&j>=0)
 85     {
 86         if(i>=0&&sc[i].first>=q[j].first)
 87         {
 88             //printf("up:%d %d\n",sc[i].second,-sc[i].first);
 89             update(1,sc[i].second,sc[i].second,INF-sc[i].first);
 90             i--;
 91         }
 92         else
 93         {
 94             ans=-9999999999;
 95             //printf("qu:%d %d\n",q[j].second.first.first,q[j].second.first.second);
 96             query(1,q[j].second.first.first,q[j].second.first.second);
 97             ansans[q[j].second.second]=min(ansans[q[j].second.second],(INF-ans)-q[j].first);
 98             j--;
 99         }
100     }
101 }
102 int main()
103 {
104     int cas=1;
105     scanf("%d",&t);
106     while(t--)
107     {
108         scanf("%d%d",&n,&qnum);
109         bulid(1,1,n);
110         for(i=0;i<n;i++)
111         {
112             scanf("%d",&sc[i].first);
113             sc[i].second=i+1;
114         }
115         sort(sc,sc+n);
116         for(i=0;i<qnum;i++)
117         {
118             int l,r;
119             scanf("%d%d%d",&l,&r,&q[i].first);
120             if(l<=0) l=1;
121             if(r>n) r=n;
122             q[i].second.first.first=l;
123             q[i].second.first.second=r;
124             q[i].second.second=i;
125         }
126         sort(q,q+qnum);
127         i=0;j=0;
128         while(i<=n&&j<qnum)
129         {
130             if(i<n&&sc[i].first<=q[j].first)
131             {
132                 //printf("up:%d %d\n",sc[i].second,sc[i].first);
133                 update(1,sc[i].second,sc[i].second,sc[i].first);
134                 i++;
135             }
136             else
137             {
138                 ans=-9999999999;
139                 //printf("qu:%d %d\n",q[j].second.first.first,q[j].second.first.second);
140                 query(1,q[j].second.first.first,q[j].second.first.second);
141                 ansans[q[j].second.second]=q[j].first-ans;
142                 j++;
143             }
144         }
145         go();
146         printf("Case #%d:\n",cas++);
147         for(i=0;i<qnum;i++)
148         {
149             printf("%d\n",ansans[i]);
150         }
151     }
152     return 0;
153 }
View Code

 

posted on 2015-05-09 17:26  T^T  阅读(333)  评论(0编辑  收藏  举报

导航