Codeforces Round #171 (Div. 2) C. Ladder(二分)

 

题目大意

 

给你一组数 a(1),a(2),a(3),...,a(n) (n<=10^5),以及 m(m<=10^5) 个 query,每个 query 的格式为 l(i) r(i),问数组中从 l(i) 到 r(i) 中的数是否是一个 lander(梯子?)

一个 lander 的定义是:对于一列数 b(1),b(2),b(3),...,b(k),存在一个数 x(1<=x<=k),使得:b(1)<=b(2)<=b(3)<=...<=b(x)<=b(x+1)<=...<=b(k)

 

做法分析

 

定义两个数组:inc[]dec[]

        初始化 inc[0]=dec[0]=0

        对于 inc 数组,如果 a(i)>=a(i-1) 那么 inc[i]=inc[i-1]+1 否则 inc[i]=inc[i-1]-1

        对于 dec 数组,如果 a(i)<=a(i-1) 那么 dec[i]=dec[i-1]+1 否则 dec[i]=dec[i-1]-1

这两个数组有这样的性质:

        如果 a(i)<=a(i+1)<=...<=a(j) 那么就有 inc[j]-inc[i]==j-i

        如果 a(i)>=a(i+1)>=...>=a(j) 那么就有 dec[j]-dec[i]==j-i

 

知道了这两个数组的性质,就可以利用二分来解决此题了,对每一个 query 具体做法就是

        先找到最大的 k(k<=r(i)) 使得 a(l(i))<=a(l(i)+1)<=...<=a(k) (这里可以用二分查找哦!!)

        再判断 dec[r(i)]-dec[k] 是否等于 r(i)-k,如果是,那么这一段是一个 lander,否则不是

 

参考代码

 

Ladder
 1 #include <cstring>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 
 6 const int N=100006;
 7 
 8 int inc[N], dec[N];
 9 int n, m, a[N];
10 
11 int main()
12 {
13     scanf("%d%d", &n, &m);
14     for(int i=1; i<=n; i++) scanf("%d",&a[i]);
15     inc[0]=dec[0]=0;
16     inc[1]=dec[1]=1;
17     for(int i=2; i<=n; i++)
18     {
19         dec[i]=dec[i-1];
20         inc[i]=inc[i-1];
21         if(a[i]>a[i-1]) dec[i]--;
22         else dec[i]++;
23         if(a[i]<a[i-1]) inc[i]--;
24         else inc[i]++;
25     }
26 
27     for(int i=0; i<m; i++)
28     {
29         int st, en;
30         scanf("%d%d", &st, &en);
31         int L=st, R=en;
32         while(L<R)
33         {
34             int mid=(L+R)>>1;
35             if(inc[mid]-inc[st]<mid-st) R=mid;
36             else L=mid+1;
37         }
38         if(inc[L]-inc[st]<L-st) L--;
39         if(dec[en]-dec[L]!=en-L) printf("No\n");
40         else printf("Yes\n");
41     }
42     return 0;
43 }

AC通道

Codeforces Round #171 (Div. 2) C. Ladder

原文地址:https://www.cnblogs.com/zhj5chengfeng/p/2949140.html