最近真是感觉自己学的知识太少了。需要更深的知识丰富自己了。发现也好久没更新博客了,,,
| There are multiple test cases.
Output For each test case, output Q lines, each containing an integer denoting the maximum circumference.
Sample Input 5 3 2 5 6 5 2 1 3 2 4 2 5
Sample Output 13 16 16
Source 2019 Multi-University Training Contest 2
Recommend liuyiding | We have carefully selected several similar problems for you: 6623 6622 6621 6620 6619 |
思路:
区间三角形满足斐波那契数,所以只需要用主席树求出区间的前44大进行查询即可。
其实之前有自己涉及过主席树,不过思路到时不难理解,就是代码实现起来有点复杂,就是在每一个节点都建一颗权值线段树,然后可用树减树找到对应区间的值。
前置:
数据离散化+getid+insert+query
数据离散化:就是把每个数按大小排序,仅记录其大小关系,可用vector 存储,如 6 9 7 5 4 离散化的结果为:3 5 4 2 1;
getid:求得对应数的大小的下标即离散化的值;
insert :建树
query 询问区间
具体可看此视频简单易懂:https://www.bilibili.com/video/av56485341/?p=2
主席树有很多细节,可要耐心学喽,而且处理起来很优美!
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define pi acos(-1.0)
const int maxx=1e5+100;
vector <ll> v;
ll a[maxx];
struct stu{
ll l,r,sum;
}A[maxx*32];
ll cnt=0,root[maxx];
ll read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
ll getid(ll x)
{
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void insert(ll l,ll r,ll pre ,ll &now,ll p)
{
A[++cnt]=A[pre];
now=cnt;
A[now].sum++;
if(l==r) return ;
ll m=(l+r)>>1;
if(p<=m)
insert(l,m,A[pre].l,A[now].l,p);// left
else
insert(m+1,r,A[pre].r,A[now].r,p);// right
}
ll query(ll l,ll r,ll L,ll R,ll k)
{
if(l==r) return l;
ll m=(l+r)>>1;
ll temp=A[A[R].l].sum-A[A[L].l].sum;
if(k<=temp)
return query(l,m,A[L].l,A[R].l,k);
else
return query(m+1,r,A[L].r,A[R].r,k-temp);
}
int main()
{
ll m,j,k,i,t,temp,n;
cnt=0;
while(scanf("%lld%lld",&n,&m))
{
v.clear();
cnt=0;
for(i=1;i<=n;i++)
{
v.push_back(a[i]=read());
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(i=1;i<=n;i++)
{
insert(1,n,root[i-1],root[i],getid(a[i]));
}
while(m--)
{
ll l,r;
l=read();r=read();
ll b[50];
if(r-l+1<=2)
{
printf("-1\n");
continue;
}
ll x=0;
int flag=0;
for(i=r-l+1;i>=r-l-44&&i>=1;i--)
{
b[++x]=v[query(1,n,root[l-1],root[r],i)-1];
if(x>=3&&b[x]>(b[x-1]+b[x-2]))
{
printf("%lld\n",b[x]+b[x-1]+b[x-2]);
flag=1;
i=-1;
break;
}
}
if(flag==0)
{
printf("-1\n");
}
}
}
return 0;
}
本文介绍如何使用主席树解决区间三角形问题,通过数据离散化、主席树的构建与查询,实现对区间内最大三角形周长的快速求解。文章详细解释了主席树的工作原理,包括节点构建、区间查询等关键步骤,并提供了完整的代码实现。

被折叠的 条评论
为什么被折叠?



