CF 689D A区间最大值等于B区间最小值的区间个数统计

  1 /*
  2   Source :CF689D
  3   题意:给出a,b两个长度为n的数组,问有多少个区间满足max(a[l,r])==min(b[l,r])  len(a)<10^5
  4   思路:对于一个固定的l,max(a[l,r])是一个单调不减的序列,min(b[l,r])是一个单调不增的序列,
  5         于是可以枚举区间的左端点,然后二分判断右端点的范围
  6         快速查询区间的最大最小值可以利用ST表实现。
  7   时间   :2018-08-14-12.26
  8 */
  9 #include <bits/stdc++.h>
 10 using namespace std;
 11
 12 typedef long long LL;
 13 const int MAXN=200005;
 14 const LL MOD7 = 1e9+7;
 15
 16 struct Min_STable
 17 {
 18     // int a[MAXN];
 19     int dp[MAXN][20];
 20     void init(int *a, int n)
 21     {
 22         for (int i=1;i<=n;++i) dp[i][0]=a[i];
 23         for (int j=1;(1<<j)<=n;++j)
 24         {
 25             for (int i=1;i+(1<<j)-1<=n;++i)
 26             {
 27                 dp[i][j]=(dp[i][j-1]<dp[i+(1<<(j-1))][j-1]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1]);
 28             }
 29         }
 30     }
 31     int query(int x,int y)
 32     {
 33         if (x>y) swap(x,y);
 34         int k=log(y-x+1)/log(2);
 35         return (dp[x][k]<dp[y-(1<<k)+1][k]?dp[x][k]:dp[y-(1<<k)+1][k]);
 36     }
 37 }Min_st;
 38
 39 struct Max_STable
 40 {
 41     int dp[MAXN][20];
 42     void init(int *a,int n)
 43     {
 44         for (int i=1;i<=n;++i) dp[i][0]=a[i];
 45         for (int j=1;(1<<j)<=n;++j)
 46         {
 47             for (int i=1;i+(1<<j)-1<=n;++i)
 48             {
 49                 dp[i][j]=(dp[i][j-1]>dp[i+(1<<(j-1))][j-1]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1]);
 50             }
 51         }
 52     }
 53     int query(int x,int y)
 54     {
 55         if (x>y) swap(x,y);
 56         int k=log(y-x+1)/log(2);
 57         return (dp[x][k]>dp[y-(1<<k)+1][k]?dp[x][k]:dp[y-(1<<k)+1][k]);
 58     }
 59 }Max_st;
 60
 61 int a[MAXN];
 62 int b[MAXN];
 63 int n;
 64
 65 void work()
 66 {
 67     Max_st.init(a,n);
 68     Min_st.init(b,n);
 69     LL ans=0;
 70     for (int i=1;i<=n;++i)
 71     {
 72         if (a[i]>b[i]) continue;
 73         if (Max_st.query(i,n)<Min_st.query(i,n)) continue;
 74         int l=i,r=n;
 75         int ml;
 76         while (l<=r)
 77         {
 78             ml=(l+r)/2;
 79             // printf("l=%d r=%d ml=%d id_A=%d id_B=%d max_A=%d min_b=%d\n",l,r,ml,Max_st.query(a,i,ml),Min_st.query(b,i,ml),a[Max_st.query(a,i,ml)],b[Min_st.query(b,i,ml)]);
 80             if (Max_st.query(i,ml)>=Min_st.query(i,ml)) r=ml-1;
 81             else l=ml+1;
 82         }
 83         if (Max_st.query(i,r+1)!=Min_st.query(i,r+1)) continue;
 84         int pl = r+1;
 85         l=i,r=n;
 86         while (l<=r)
 87         {
 88             ml=(l+r)/2;
 89             // printf("2 l=%d r=%d ml=%d\n",l,r,ml);
 90             if (Max_st.query(i,ml)<=Min_st.query(i,ml)) l=ml+1;
 91             else r=ml-1;
 92         }
 93         ans+=(LL) (l-pl);
 94     }
 95     printf("%I64d\n",ans);
 96 }
 97
 98 int main()
 99 {
100 #ifndef ONLINE_JUDGE
101     freopen("test.txt","r",stdin);
102 #endif // ONLINE_JUDGE
103     scanf("%d",&n);
104     for (int i=1;i<=n;++i) scanf("%d",&a[i]);
105     for (int i=1;i<=n;++i) scanf("%d",&b[i]);
106     work();
107     return 0;
108 }
109
110 //in[1]:
111 //6
112 //1 2 3 2 1 4
113 //6 7 1 2 3 2
114
115 //out[1]:
116 //2

原文地址:https://www.cnblogs.com/LeeSongt/p/9478798.html

时间: 2024-08-30 15:54:51

CF 689D A区间最大值等于B区间最小值的区间个数统计的相关文章

B - I Hate It HDU - 1754 线段树区间最大值板子(单点更新,区间最大)

第一次打 改了半天  各种小错误 难受 1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int maxn=2000000+7; 5 int a[maxn],n; 6 struct Node{ 7 int l,r; 8 long long Max,lazy; 9 void update(long long val){ 10 ;//本题没用 11 } 12 }tree[maxn*5]; 13

【RMQ问题】求数组区间最大值

转自:http://blog.csdn.net/lilongherolilong/article/details/6624390 先挖好坑,明天该去郑轻找虐 RMQ(Range Minimum/Maximum Query)问题是求区间最值问题.你当然可以写个O(n)的(怎么写都可以吧=_=),但是万一要询问最值1000000遍,估计你就要挂了.这时候你可以放心地写一个线段树(前提是不写错)应该不会挂.但是,这里有更简单的算法,就是ST算法,它可以做到O(nlogn)的预处理,O(1)地回答每个询

hdu1754 区间更新查询(单点更新+查询求区间最大值)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 106776    Accepted Submission(s): 40096 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的

线段树|计蒜客:最甜的苹果-区间最大值

最甜的苹果 蒜头君有很多苹果,每个苹果都有对应的甜度值. 蒜头君现在想快速知道从第i个苹果到第j个苹果中,最甜的甜度值是多少. 因为存放时间久了,有的苹果会变甜,有的苹果会因为腐烂而变得不甜,所以蒜头君有时候还需要修改第i个苹果的甜度值.输入格式 第一行输入两个正整数N,M(0<N≤200000,0<M<5000),分别代表苹果的个数和蒜头君要进行的操作的数目. 每个苹果从1到N进行编号. 接下来一行共有N个整数,分别代表这N个苹果的初始甜度值. 接下来M行.每一行有一个字符C,和两个正

树状数组求区间最大值

------  一直用 线段树 求区间最大值,想换种思路,用树状数组试试,肯定是可以的. 首先要对 树状数组的每个 i 所管理的区间有一定的理解.详见上篇博客: 树状数组(BIT)

hdu1754(线段数维护区间最大值)

题意:给定1-n(n<=200000)个数,然后动态改变一些值,并动态询问区间最大值. 解法:裸的线段树,赛前默写模版回忆下线段树代码.仍然要注意:线段树节点数组一定要开到节点数的三倍长度. 代码: /****************************************************** * author:xiefubao *******************************************************/ #pragma comment(lin

hdoj 2795 Billboard【线段树区间最大值】

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16023    Accepted Submission(s): 6770 Problem Description At the entrance to the university, there is a huge rectangular billboard of s

POJ3264 Balanced Lineup 线段树区间最大值 最小值

Q个数 问区间最大值-区间最小值 1 // #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <sstream> 6 #include <string> 7 #include <algorithm> 8 #i

HDU 1754 多个学生偷改成绩问最高分-线段树-(单点替换,区间最大值)

题意:n个学生有初始成绩,现在有m个操作,(Q,a,b):询问区间学号为[a,b]的学生的最好成绩:(U,a,b):修改学号为a的学生的成绩为b,要你执行这m项操作. 分析: 单点更新,区间查询.确切的说是单点替换,区间查询.线段的典型用法之二. 代码: #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=200000; int n,m;