• 【LG2481】[SDOI2011]拦截导弹


    【LG2481】[SDOI2011]拦截导弹

    题面

    洛谷

    题解

    可以看出第一问就是一个有关偏序的(LIS),很显然可以用(CDQ)优化

    关键在于第二问

    概率(P_i=) (总LIS数) / (经过i的LIS数)

    分别正反跑两遍(CDQ)可以统计出分别以(i)为终点和起点的(LIS)

    乘起来就是经过(i)的方案数

    比较坑的一点是(long) (long)存不下,要用(double)

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector> 
    using namespace std;
    namespace IO { 
        const int BUFSIZE = 1 << 20; 
        char ibuf[BUFSIZE], *is = ibuf, *it = ibuf; 
        inline char gc() { 
            if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); 
    		return *is++; 
        } 
    } 
    inline int gi() {
        register int data = 0, w = 1;
        register char ch = 0;
        while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc();
        if (ch == '-') w = -1 , ch = IO::gc();
        while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc();
        return w * data;
    } 
    const int MAX_N = 50005; 
    struct Node {int h, v, i; } t[MAX_N]; int N; 
    bool cmp_h(const Node &a, const Node &b) { return a.h > b.h; } 
    bool cmp_v(const Node &a, const Node &b) { return a.v > b.v; } 
    bool cmp_i(const Node &a, const Node &b) { return a.i < b.i; } 
    
    inline int lb(int x) { return x & -x; } 
    int c[MAX_N]; double w[MAX_N]; 
    void add(int x, int v, double W) { 
    	while (x <= N) { 
    	    if (v == c[x]) w[x] += W; 
    	    else if (v > c[x]) c[x] = v, w[x] = W; 
    	    x += lb(x); 
        } 
    } 
    int sum(int x) { 
        int res = 0;
    	while (x > 0) res = max(res, c[x]), x -= lb(x); 
    	return res; 
    } 
    double sum(int x, int v) { 
        double res = 0; 
    	while (x > 0) res += (c[x] == v) ? w[x] : 0, x -= lb(x); 
    	return res; 
    } 
    void Set(int x) { while (x <= N) c[x] = w[x] = 0, x += lb(x); } 
    
    int f[2][MAX_N]; double g[2][MAX_N]; 
    void Div(int l, int r, int type) { 
    	if (l == r) return ; 
    	sort(&t[l], &t[r + 1], cmp_i); 
    	if (type) reverse(&t[l], &t[r + 1]); 
    	int mid = (l + r) >> 1; 
    	Div(l, mid, type); 
    	sort(&t[l], &t[mid + 1], cmp_h); 
    	sort(&t[mid + 1], &t[r + 1], cmp_h); 
    	int j = l; 
    	for (int i = mid + 1; i <= r; i++) { 
    	    while (j <= mid && t[j].h >= t[i].h) 
    	        add(N + 1 - t[j].v, f[type][t[j].i], g[type][t[j].i]), ++j; 
            int res = sum(N + 1 - t[i].v) + 1; 
            if (res > f[type][t[i].i]) 
    		    f[type][t[i].i] = res, g[type][t[i].i] = sum(N + 1 - t[i].v, res - 1); 
    		else if (res == f[type][t[i].i]) g[type][t[i].i] += sum(N + 1 - t[i].v, res - 1); 
        } 
        for (int i = l; i <= mid; i++) Set(N + 1 - t[i].v); 
        Div(mid + 1, r, type); 
    } 
    int Sh[MAX_N], toth, Sv[MAX_N], totv; 
    int main () { 
        N = gi(); 
        for (int i = 1; i <= N; i++) t[i] = (Node){gi(), gi(), i}; 
        for (int i = 1; i <= N; i++) Sh[++toth] = t[i].h;
        sort(&Sh[1], &Sh[toth + 1]); toth = unique(&Sh[1], &Sh[toth + 1]) - Sh - 1; 
        for (int i = 1; i <= N; i++) t[i].h = lower_bound(&Sh[1], &Sh[toth + 1], t[i].h) - Sh;
        for (int i = 1; i <= N; i++) Sv[++totv] = t[i].v;
        sort(&Sv[1], &Sv[totv + 1]); totv = unique(&Sv[1], &Sv[totv + 1]) - Sv - 1;
        for (int i = 1; i <= N; i++) t[i].v = lower_bound(&Sv[1], &Sv[totv + 1], t[i].v) - Sv; 
        for (int i = 1; i <= N; i++) f[0][i] = f[1][i] = g[0][i] = g[1][i] = 1; 
        Div(1, N, 0); reverse(&t[1], &t[N + 1]); 
        for (int i = 1; i <= N; i++) t[i].v = N + 1 - t[i].v, t[i].h = N + 1 - t[i].h; 
        Div(1, N, 1); 
        int ans = 0; double ss = 0; 
        for (int i = 1; i <= N; i++) ans = max(ans, f[0][i]); 
        for (int i = 1; i <= N; i++) if (f[0][i] == ans) ss += g[0][i]; 
        printf("%d
    ", ans); 
        for (int i = 1; i <= N; i++) 
            if (f[0][i] + f[1][i] - 1 != ans) printf("0.000000 "); 
            else printf("%0.6lf ", g[0][i] * g[1][i] / ss); 
        printf("
    "); 
        return 0; 
    } 
    
  • 相关阅读:
    .net core + mvc 手撸一个代码生成器
    如何使用VS Code编写Spring Boot (第二弹)
    第五章 .net core该怎么玩
    第四章 .net core做一个简单的登录
    第三章 搭建一个通用的权限管理系统
    第二章 在Linux上部署.net core
    将博客搬至CSDN
    Entity Framework6 with Oracle(可实现code first)
    利用windbg查找dictionary导致IIS占CPU100%案例分析(一)
    VS快捷键以及Reshaper快捷键
  • 原文地址:https://www.cnblogs.com/heyujun/p/10122127.html
Copyright © 2020-2023  润新知