题意:

给定一个数列,每次询问一个区间,问这个区间中的值可组成的周长最大的三角形的周长。

题解:

定理1:给定一些值,这些值中组成边长最大的三角形的三条边的大小排名一定是连续的。

证明:假如第k大,第k+1大,第k+2+b(b>0)大的三条边组成了一个边长最大的三角形,那么较小的两条边加起来长度大于第三边,又因为第k+2大的边比第k+2+b大的边长,因此把第k+2+b大的边换成第k+2大的边组成的三角形边长一定比原来大,矛盾。

定理2:如果三角形边长被限制为1e9以内的正整数,那么如果某组值存在周长最大的三角形,一定由前45大的边组成

证明:假如三角形由第44,45,46大的边组成,那么由定理1,前45大的边都组不成三角形,不妨令这个已组成的三角形的周长最小,三边分别为1,1,1,那么,如果要让第k,k+1,k+2大的三条边组不成三角形,必须令第k大的边大于等于后两条边之和。不难推出,第k大的边大于等于Febnacci[46-k],最大的边至少为Feb[45],已经超出1e9的范围,矛盾

有了这两个命题,此题的解法就一目了然,对于每个询问,找出该区间内前45大的值,依次询问排名连续的三个是否能构成三角形。

用主席树维护区间第k大,复杂度O(qlogn*c)    (c=45)

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int MAXN = 1e5 + ;
struct node {
int ls, rs, sum;
//左子树,右子树,该节点值
} ns[MAXN * ]; int ct;
//时间节点
int rt[MAXN * ];
//rt[i]代表a[i]在树上是第几个添加的 void cpy(int& now, int old) {
now = ++ct;
ns[now] = ns[old];
} void pushUp(int& now) {
ns[now].sum = ns[ns[now].ls].sum + ns[ns[now].rs].sum;
} void build(int& now, int l, int r) {
now = ++ct;
ns[now].sum = ;
if (l == r) return;
int m = (l + r) >> ;
build(ns[now].ls, l, m);
build(ns[now].rs, m + , r);
} void update(int& now, int old, int l, int r, int x) {
cpy(now, old);
//在旧树上添加新树
if (l == r) {
ns[now].sum++;
return;
}
int m = (l + r) >> ;
if (x <= m) update(ns[now].ls, ns[old].ls, l, m, x);
else update(ns[now].rs, ns[old].rs, m + , r, x);
pushUp(now);
//向上更新节点权值
} int query(int s, int t, int l, int r, int k) {
if (l == r) return l;
int m = (l + r) >> ;
int cnt = ns[ns[t].ls].sum - ns[ns[s].ls].sum;
//cout << s << " " << t << " " << cnt << endl;
if (k <= cnt) return query(ns[s].ls, ns[t].ls, l, m, k);
return query(ns[s].rs, ns[t].rs, m + , r, k - cnt);
//
} void init(int n) {
ct = ;
build(rt[], , n);
//从头开始建立主席树
} int a[MAXN], b[MAXN];
//b数组是a数组去重后的结果 int solve(int n,int m) { // int n, m;
// scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + , b + n + );
int sz = unique(b + , b + + n) - b - ;
init(sz);
//初始化树
for (int i = ; i <= n; i++) {
a[i] = lower_bound(b + , b + + sz, a[i]) - b;
//找出当前要添加的节点是b的第几个
update(rt[i], rt[i - ], , sz, a[i]);
//更新这个点
}
/*for (int i = 0; i <= 5 * n; i++) {
printf("%d, rt = %d, ls = %d, rs = %d, sum = %d\n", i, rt[i], ns[rt[i]].ls, ns[rt[i]].rs, ns[rt[i]].sum);
}*/
while (m--) {
int ll,rr;
scanf("%d %d",&ll,&rr);
vector<int> vec;
vec.clear();
for(int i=;i<=min(,rr-ll+);i++){
vec.push_back(b[query(rt[ll-],rt[rr],,sz,rr-ll+-i)]);
// printf("push%d\n",vec[vec.size()-1]);
}
LL ans=-;
for(int i=;i<vec.size();i++){
if(vec[i-]<vec[i-]+vec[i]){
ans=1LL*vec[i-]+vec[i]+vec[i-];
break;
}
}
printf("%lld\n",ans);
// printf("%d\n", b[query(rt[s - 1], rt[t], 1, sz, k)]);
}
return ;
}
int main(){
int n,m;
while(){
int rep=scanf("%d %d",&n,&m);
if(rep==-)break;
else {
// memset()
solve(n,m);
}
}
}

hdu多校第二场1011 (hdu6601) Keen On Everything But Triangle 主席树的更多相关文章

  1. HDU - 6601 Keen On Everything But Triangle 主席树

    Keen On Everything But Triangle 感觉最近多校好多主席树的亚子,但是本人菜得很,还没学过主席树,看着队友写题就只能划水,\(WA\)了还不能帮忙\(debug\),所以深 ...

  2. 2014多校第二场1011 || HDU 4882 ZCC Loves Codefires (贪心)

    题目链接 题意 : 给出n个问题,每个问题有两个参数,一个ei(所要耗费的时间),一个ki(能得到的score).每道问题需要耗费:(当前耗费的时间)*ki,问怎样组合问题的处理顺序可以使得耗费达到最 ...

  3. hdu 6055 : Regular polygon (2017 多校第二场 1011) 【计算几何】

    题目链接 有个结论: 平面坐标系上,坐标为整数的情况下,n个点组成正n边形时,只可能组成正方形. 然后根据这个结论来做. 我是先把所有点按照 x为第一关键字,y为第二关键字 排序,然后枚举向量 (p[ ...

  4. HDU6602 Longest Subarray hdu多校第二场 线段树

    HDU6602 Longest Subarray 线段树 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6602 题意: 给你一段区间,让你求最长的区间使 ...

  5. hdu多校第二场1008(hdu6598) Harmonious Army 最小割

    题意: 一个军队有n人,你可以给他们每个人安排战士或者法师的职业,有m对人有组合技,组合技的信息是a,b,c,代表如果这两个人是两个战士,则组合技威力为a,一个战士一个法师,威力为b,其中b=a/4+ ...

  6. hdu多校第二场 1005 (hdu6595) Everything Is Generated In Equal Probability

    题意: 给定一个N,随机从[1,N]里产生一个n,然后随机产生一个n个数的全排列,求出n的逆序数对的数量,加到cnt里,然后随机地取出这个全排列中的一个非连续子序列(注意这个子序列可以是原序列),再求 ...

  7. hdu多校第二场1009 (hdu6599) I Love Palindrome String 回文自动机/字符串hash

    题意: 找出这样的回文子串的个数:它本身是一个回文串,它的前一半也是一个回文串 输出格式要求输出l个数字,分别代表长度为1~l的这样的回文串的个数 题解: (回文自动机和回文树是一个东西) 首先用回文 ...

  8. hdu多校第二场 1010 (hdu6600)Just Skip This Problem

    题意: 给你一个数x,允许你多次询问yi,然后回答你x xor yi 是否等于yi,询问尽量少的次数以保证能求出xi是几,求出这样询问次数最少的询问方案数. 结果mod1e6+3 题解: 队友赛时很快 ...

  9. 2019牛客多校第二场 A Eddy Walker(概率推公式)

    2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...

随机推荐

  1. Linux下Qt调用共享库文件.so

    修改已有的pro文件,添加如下几句: INCLUDEPATH += /home/ubuntu/camera/camera/LIBS += -L/home/ubuntu/camera/camera -l ...

  2. Python学习笔记(九)——字符串

    # 5.1 字符串的拼接 str1 = '我今天一共走了' num = 1280 str2 = '步' print(str1+str(num)+str2) # 计算字符串长度 print(len(st ...

  3. line-height 行高的使用

    line-height:normal; 默认  字体 line-height:1.5; line-height:200%; line-height:50px;  ps : 固定的值 line-heig ...

  4. shell脚本中关于日期的操作

    一.计算指定日期的前一天的日期 date -d "yesterday 20150401 " +%Y%m%d 二.如果获取当前日期的前一天        date -d " ...

  5. Go Mixed 变量声明

    Go Mixed 变量声明 package main import "fmt" func main() { var a, b, c = 3, 4, "foo" ...

  6. 线性基算贡献——19牛客多校第一场H

    /* 给定数组a[],求有多少集合的异或值为0,将这些集合的大小之和求出来 对于每个数来说,如果除去这个数后数组里做出的线性基和这个数线性相关,那么这个数贡献就是2^(n-1-线性基的大小) 反之这个 ...

  7. NX二次开发-UFUN工程图插入PNG图片UF_DRF_create_image_from_file

    #include <uf.h> #include <uf_drf.h> UF_initialize(); //插入PNG char* file_name = "D:\ ...

  8. 修改ActiveProcessLinks链表隐藏进程

    在Windows内核中有一个活动进程链表AcvtivePeorecssList.它是一个双向链表,保存着系统中所有进程的EPROCESS结构.特别地,进程的EPROCESS结构包含一个具有指针成员FL ...

  9. Python中的startswith和endswith函数使用实例

    Python中的startswith和endswith函数使用实例 在Python中有两个函数分别是startswith()函数与endswith()函数,功能都十分相似,startswith()函数 ...

  10. 普通用户授予root权限

    开始用linux的时候会遇到用户权限问题,比如安装软件的时候经常会提示权限不足,下面介绍给普通用户授予root权限. 找到  cd /etc/sudoers可以看到用户的权限是:只有读取的权限(以下操 ...