zoukankan      html  css  js  c++  java
  • Bzoj2244: [SDOI2011]拦截导弹

    题面

    传送门

    Sol

    每个导弹有时间,高度,速度
    求时间递增,高度,速度不降的最长的序列
    然后还要求最长序列的方案以及每个导弹在最长序列中的方案

    这个就是偏序问题辣,正反两遍求出每个导弹为结尾开头的序列最长长度
    判断是否在最长序列就二者相加判断
    然后记录下方案,用(double)(long long)会炸

    然后我选择(CDQ)

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    const int _(5e4 + 5);
    typedef long long ll;
    
    IL int Input(){
    	RG int x = 0, z = 1; RG char c = getchar();
    	for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    	for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	return x * z;
    }
    
    int n, g[2][_], c1[_], o1[_], len1, o2[_], len2;
    double f[2][_], c2[_];
    struct Missile{
    	int id, h, v;
    
    	IL void Reverse(){
    		id = n - id + 1, h = len1 - h + 1, v = len2 - v + 1;
    	}
    
    	IL int operator <(RG Missile B) const{
    		return h != B.h ? h < B.h : id < B.id;
    	}
    } q[_], p[_];
    
    IL void Cls(RG int x){
    	for(; x <= len2; x += x & -x) c1[x] = c2[x] = 0;
    }
    
    IL void Add(RG int x, RG int l, RG double p){
    	for(; x <= len2; x += x & -x)
    		if(l > c1[x]) c1[x] = l, c2[x] = p;
    		else if(l == c1[x]) c2[x] += p;
    }
    
    IL void Query(RG int x, RG int &l, RG double &p){
    	for(; x; x -= x & -x)
    		if(c1[x] > l) l = c1[x], p = c2[x];
    		else if(c1[x] == l) p += c2[x];
    }
    
    IL void CDQ(RG int l, RG int r, RG int op){
    	if(l == r) return;
    	RG int mid = (l + r) >> 1;
    	for(RG int i = l, be = l, en = mid + 1; i <= r; ++i)
    		if(q[i].id <= mid) p[be++] = q[i];
    		else p[en++] = q[i];
    	for(RG int i = l; i <= r; ++i) q[i] = p[i];
    	CDQ(l, mid, op);
    	for(RG int i = mid + 1, j = l; i <= r; ++i){
    		while(j <= mid && q[j].h <= q[i].h) Add(q[j].v, g[op][q[j].id] + 1, f[op][q[j].id]), ++j;
    		Query(q[i].v, g[op][q[i].id], f[op][q[i].id]);
    	}
    	for(RG int i = l; i <= mid; ++i) Cls(q[i].v);
    	CDQ(mid + 1, r, op);
    	for(RG int i = l, be = l, en = mid + 1; i <= r; ++i)
    		if(en > r || (be <= mid && q[be].h <= q[en].h)) p[i] = q[be++];
    		else p[i] = q[en++];
    	for(RG int i = l; i <= r; ++i) q[i] = p[i];
    }
    
    int main(RG int argc, RG char* argv[]){
    	n = Input();
    	for(RG int i = 1; i <= n; ++i){
    		q[i] = (Missile){i, Input(), Input()};
    		o1[++len1] = q[i].h, o2[++len2] = q[i].v;
    	}
    	sort(o1 + 1, o1 + len1 + 1), sort(o2 + 1, o2 + len2 + 1);
    	len1 = unique(o1 + 1, o1 + len1 + 1) - o1 - 1;
    	len2 = unique(o2 + 1, o2 + len2 + 1) - o2 - 1;
    	for(RG int i = 1; i <= n; ++i){
    		q[i].h = lower_bound(o1 + 1, o1 + len1 + 1, q[i].h) - o1;
    		q[i].v = lower_bound(o2 + 1, o2 + len2 + 1, q[i].v) - o2;
    		q[i].h = len1 - q[i].h + 1, q[i].v = len2 - q[i].v + 1;
    		g[0][i] = g[1][i] = 1, f[0][i] = f[1][i] = 1;
    	}
    	sort(q + 1, q + n + 1), CDQ(1, n, 0);
    	for(RG int i = 1; i <= n; ++i) q[i].Reverse();
    	sort(q + 1, q + n + 1), CDQ(1, n, 1);
    	reverse(g[1] + 1, g[1] + n + 1), reverse(f[1] + 1, f[1] + n + 1);
    	RG int mx = 0; RG double sum = 0;
    	for(RG int i = 1; i <= n; ++i) mx = max(mx, g[0][i]);
    	printf("%d
    ", mx);
    	for(RG int i = 1; i <= n; ++i) if(g[0][i] == mx) sum += f[0][i];
    	for(RG int i = 1; i <= n; ++i){
    		if(g[0][i] + g[1][i] - 1 != mx) puts("0");
    		else printf("%.5lf
    ", f[0][i] * f[1][i] / sum);
    	}
        return 0;
    }
    
  • 相关阅读:
    我的大学,我的梦想
    c++读取lua配置基础类
    无奖调查,你希望我写哪些题材的文章
    无奖调查,你希望我写哪些题材的文章
    lua不同模块调用
    cmake配置c++可调用的文件路径参数
    Java实现 LeetCode 335 路径交叉
    Java实现 LeetCode 335 路径交叉
    Java实现 LeetCode 335 路径交叉
    Java实现 LeetCode 334 递增的三元子序列
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8717494.html
Copyright © 2011-2022 走看看