Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)
Posted lis-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)相关的知识,希望对你有一定的参考价值。
题目:http://codeforces.com/contest/1156/problem/E
题意:给你1-n n个数,然后求有多少个区间[l,r] 满足 a[l]+a[r]=max([l,r])
思路:首先我们去枚举区间肯定不现实,我们只能取把能用的区间去用,我们可以想下每个数当最大值的时候所做的贡献
我们既然要保证这个数为区间里的最大值,我们就要从两边扩展,找到左右边界能扩展在哪里,这里你直接去枚举肯定不行
这里我们使用了线段树二分去枚举左右区间最远能走到哪里,然后很暴力的去枚举短的那一边找出右边是否有满足条件的边界
#include<bits/stdc++.h> #define maxn 200005 #define mod 1000000007 using namespace std; typedef long long ll; struct sss { int l,r; int val; }tree[maxn*4]; int n; int a[maxn]; int pos[maxn]; void build(int cnt,int l,int r) { if(l==r){ tree[cnt].l=l; tree[cnt].r=r; tree[cnt].val=a[l]; return; } tree[cnt].l=l; tree[cnt].r=r; int mid=(l+r)/2; build(cnt*2,l,mid); build(cnt*2+1,mid+1,r); tree[cnt].val=max(tree[cnt*2].val,tree[cnt*2+1].val); } int query(int cnt,int l,int r) { if(l<=tree[cnt].l&&r>=tree[cnt].r) return tree[cnt].val; int mid=(tree[cnt].l+tree[cnt].r)/2; if(r<=mid) return query(cnt*2,l,r); else if(l>mid) return query(cnt*2+1,l,r); else{ return max(query(cnt*2,l,mid),query(cnt*2+1,mid+1,r)); } } int dl(int x) { int val=a[x]; int l=1; int r=x; while(r-l>1){ int mid=(l+r)/2; int max_val=query(1,mid,x); //如果满足这个区间的最大值是这个数就继续扩张 if(max_val==val) { r=mid; } else{ l=mid; } } int max_val=query(1,l,x); if(max_val==val) return l; else return r; } int dr(int x) { int val=a[x]; int l=x; int r=n; while(r-l>1){ int mid=(l+r)/2; int max_val=query(1,x,mid); if(max_val==val) { l=mid; } else{ r=mid; } } int max_val=query(1,x,r); if(max_val==val) return r; else return l; } int main() { cin>>n; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pos[a[i]]=i; } build(1,1,n); int ans=0; for(int i=1;i<=n;i++){ int l=dl(i);//找出左边界 int r=dr(i);//找出右边界 if(i-l<r-i){//枚举短的那一边 for(int j=l;j<i;j++){ int other=a[i]-a[j]; if (other<=0||other>n)continue; ans+=pos[other]>i&&pos[other]<=r;//确定令一边是否在这个区间里面 } } else{ for(int j=i+1;j<=r;j++){ int other=a[i]-a[j]; if (other<=0||other>n)continue; ans+=pos[other]<i&&pos[other]>=l; } } } printf("%d",ans); }
以上是关于Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33