HDU6601

HDU6601
  • 题目

    HDU6601

  • 分析

    多校题。

    判断三角形能不能构成, F i b o n a c c i Fibonacci Fibonacci 数列 : 1 , 1 , 2 , 3 , 5 , 8 , 13... 1,1,2,3,5,8,13... 1,1,2,3,5,8,13... 数列中任意三个数构不成三角形,所以看最差的情况也就是第 44 44 44 位数超过了范围。所以只用判断区间中最大的 44 44 44 位数就可以了,在 44 44 44 位数中快速判断能否构成三角形且周长最长的方法是:将这 44 44 44 个数从大到小排序: a , b , c , d , e , f . . . a,b,c,d,e,f... a,b,c,d,e,f... 先判断 a , b , c a,b,c a,b,c 可不可以,看 a a a 是否小于 b + c b + c b+c ,若小于则就是 a + b + c a + b + c a+b+c 就是答案,若 a a a 大于等于 b + c b + c b+c ,因为 b , c b,c b,c 已经是数列中第二大和第三大的了,那么随便在后面取什么数都不可能大于 a a a 了。再判断 b , c , d b,c,d b,c,d 以此类推。。。

    44 44 44 大用主席树维护。。这里代码维护的第 k k k 小,一样的。。。模板扒的

    • 代码
    const int N = 2e5 + 5;
    int a[N], b[N];
    int root[N];
    int cnt = 0;
    int tot = 0;
    int q, n;
    std::vector<ll> v;
    struct ps_tree
    {
    	int lc;
    	int rc;
    	int cnt;
    } tree[N * 40];
    
    int build(int l, int r)
    {
    	int pos = ++cnt;
    	if (l == r) {
    		tree[pos].cnt = 0;
    		return pos;
    	}
    	int mid = (l + r) >> 1;
    	tree[pos].lc = build(l, mid);
    	tree[pos].rc = build(mid + 1, r);
    	return pos;
    }
    
    
    int update(int ed, int l, int r, int val)
    {
    	int pos = ++cnt;
    	tree[pos] = tree[ed];
    	if (l == r) {
    		tree[pos].cnt++;
    		return pos;
    	}
    	int mid = (l + r) >> 1;
    	if (val <= mid) tree[pos].lc = update(tree[ed].lc, l, mid, val);
    	else tree[pos].rc = update(tree[ed].rc, mid + 1, r, val);
    	tree[pos].cnt = tree[tree[pos].lc].cnt + tree[tree[pos].rc].cnt;
    	return pos;
    }
    
    ll query(int p, int q, int l, int r, int k)
    {
    	if (l == r) return l;
    	int mid = (l + r) >> 1;
    	int lcnt = tree[tree[p].lc].cnt - tree[tree[q].lc].cnt;
    	if (k <= lcnt) return query(tree[p].lc, tree[q].lc, l, mid, k);
    	else return query(tree[p].rc, tree[q].rc, mid + 1, r, k - lcnt);
    }
    
    bool cmp(int a, int b)
    {
    	return a > b;
    }
    
    int main ()
    {
    	while (~scanf("%d %d", &n, &q)) {
    		tot = 0;
    		for (int i = 1; i <= n; i++)
    		{
    			read(a[i]);
    			b[++tot] = a[i];
    		}
    		sort(b + 1, b + tot + 1);
    		tot = unique(b + 1, b + tot + 1) - (b + 1);
    		root[0] = build(1, tot);
    		for (int i = 1; i <= n; i++)
    		{
    			int pos = lower_bound(b + 1, b + tot + 1, a[i]) - b;
    			root[i] = update(root[i - 1], 1, tot, pos);
    		}
    		for (int i = 1; i <= q; i++) {
    			int l, r;
    			read(l);
    			read(r);
    			if (r - l + 1 <= 2)
    			{
    				printf("-1\n");
    				continue;
    			}
    			if (r - l + 1 > 44)
    			{
    				v.clear();
    				for (int i = (r - l + 1); i >= (r - l + 1 - 44); i--)
    				{
    					v.push_back(b[query(root[r], root[l - 1], 1, tot , i)]);
    				}
    				sort(v.begin(), v.end(), cmp);
    				ll ans = 0;
    				int flag = 0;
    				for (int i = 0; i <= v.size() - 3; i++)
    				{
    					if (v[i] < (ll)v[i + 1] + v[i + 2])
    					{
    						ans = (ll)v[i] + v[i + 1] + v[i + 2];
    						flag = 1;
    						break;
    					}
    				}
    				if (!flag) ans = -1;
    				printf("%lld\n", ans);
    			}
    			else
    			{
    				v.clear();
    				for (int i = (r - l + 1); i >= 1; i--)
    				{
    					v.push_back(b[query(root[r], root[l - 1], 1, tot, i)]);
    				}
    				sort(v.begin(), v.end(), cmp);
    				ll ans = 0;
    				int flag = 0 ;
    				for (int i = 0; i <= v.size() - 3; i++)
    				{
    					if (v[i] < (ll)v[i + 1] + v[i + 2])
    					{
    						ans = (ll)v[i] + v[i + 1] + v[i + 2];
    						flag = 1;
    						break;
    					}
    				}
    				if (!flag) ans = -1;
    				printf("%lld\n", ans);
    			}
    		}
    	}
    	return 0 ;
    }
    
  • 题型

    主席树 + 暴力

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值