• P3515 [POI2011]Lightning Conductor


    首先进行一步转化

    (a_j leq a_i + q - sqrt(abs(i - j)))

    (a_i + q geq a_j + sqrt(abs(i-j)))

    即 $q = max (a_j + sqrt(abs(i-j))) - a_i $

    我们对(i geq j 和 j > i) 分类讨论, 其实解决一种情况后将序列翻转再做一遍即可

    有一种O((n^2))的dp暴力应该不难想到

    那么我们现在思考如何以比较优秀的时间复杂度解决

    这里涉及到决策单调性

    简单的说, 对于i来说, 它的答案来源是另一点j,

    那么所有答案来源排成的序列(j_1,j_2,j_3,cdots j_n) 具有单调性

    比如: 1112255566666666678888

    那么我们可以考虑对于每一个i, 它可以成为哪一段区间的答案

    即一个三元组(l, r, i) 对应i控制l到r

    可以二分+栈(或队列)处理

    二分i和栈顶答案相等临界, 若临界小于l则弹栈重复操作

    否则将新的(l, r, i) 压倒栈中

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #define ll long long
    using namespace std;
    const int N = 500080;
    struct node{
    	ll l, r, x;
    };
    deque<node> q;
    ll read() {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (!isdigit(c)) {
    		if (c == '-') f = -1;
    		c = getchar();
    	}
    	while (isdigit(c)) {
    		x = (x << 3) + (x << 1) + c - '0';
    		c = getchar();
    	}
    	return x * f;
    } //快读
    ll n;
    long double ans[N], a[N];
    bool check(ll x,ll y,ll k) {
    	return a[x] + sqrt(k - x) > a[y] + sqrt(k - y);
    }
    void work(void) {
    	node k = (node){1, n, 1}; 
    	for (ll i = 2;i <= n; i++) {
    		if (a[i] < a[k.x]) continue; //剪枝, 如果满足则它一定不会有贡献
    		ll l = i, r = n, mid;
    		while (l <= r) {
    			mid = (l + r) >> 1;
    			if (check(k.x, i, mid)) l = mid + 1;
    			else r = mid - 1;
    		}//二分
    		if (l == n + 1) continue;
    		if (l <= k.l) {
    			k = q.front();
    			q.pop_front();
    			i--;
    			continue;
    		}//弹栈
    		k.r = r;
    		q.push_front(k);
    		k = (node){l, n, i}; //压栈
    	}
    	q.push_front(k);
    	k = q.back();
    	q.pop_back();
    	for (ll i = 1;i <= n; i++) {
    		if (k.r < i) {
    			k = q.back();
    			q.pop_back();
    		}
    		ans[i] = max(ans[i], a[k.x] + sqrt(i - k.x)); //要做两次,所以取max
    	}
    }
    		
    int main() {
    	n = read();
    	for (int i = 1;i <= n; i++) 
    		a[i] = read(), ans[i] = a[i];
    	work();
    	for (int j = 1;j << 1 <= n; j++) 
    	swap(a[j], a[n-j+1]), swap(ans[j], ans[n-j+1]);
        //翻转
    	while (q.size()) q.pop_front();
    	work();
    	///*
    	for (int i = n;i >= 1; i--)
    		printf ("%d
    ", int(ceil(ans[i]) - a[i]));
    		//*/
    	return 0;
    }
    
  • 相关阅读:
    ue4 官网IK流程记录
    ue4-C++中加载一个蓝图类(二)-C++中绑定Blueprint武器
    UE4 c++ 创建刚体Cube
    UE4的AI学习(1)——基本概念
    UE4的AI学习(2)——官方案例实例分析
    行为树(Behavior Tree)实践(1)– 基本概念
    Animation Blueprint, Set Custom Variables Via C++
    ue4 c++ anim notify
    ue4 动画相关方法杂记
    [UE4]Montage动画设置Slot
  • 原文地址:https://www.cnblogs.com/Hs-black/p/11626103.html
Copyright © 2020-2023  润新知