zoukankan      html  css  js  c++  java
  • GYM

    题意:

      一个n*n的棋盘,有m个主教。每个主教都有自己的权值p。给出一个值C,在棋盘中找到一个最大点集。这个点集中的点在同一条对角线上且对于点集中任意两点(i,j),i和j之间的主教数(包括i,j)不小于pi^2+pj^2+C。

    题解:

      对角线有2个方向,每个方向有2*n-1条对角线。一共时4*n-2条。每个点都在2条对角线上。

      对于在同一对角线上的点(i,j)若满足i-j+1>=pi^2+pj^2+C即-j-pj^2>=pi^2+C-i-1(i>j)即可。

      那么将同一对角线上的点按x坐标排序。将每个点的信息整合到一起离散化,最后用树状数组维护每个点前面满足-j-pj^2>=pi^2+C-i-1的最大值。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int, ll> P;
    const int maxn = 1e5+10;
    int t;
    int n, m;
    ll c;
    int u, v;
    ll p;
    int cnt;
    int ans;
    ll _sort[maxn<<1];
    int tree[maxn<<1];
    struct node {
        int x;
        ll val;
        node(int a, ll b) {
            x = a; val = b;
        }
    };
    vector<P> bs[2][maxn<<1]; 
    void update(int x, int val) {
        while(x <= cnt) {
            tree[x] = max(tree[x], val);
            x += x&(-x); 
        }
    }
    int sum(int x) {
        int res = 0;
        while(x > 0) {
            res = max(res, tree[x]);
            x -= x&(-x);
        }
        return res;
    }
    int main() {
        freopen("bishops.in","r",stdin);
        scanf("%d", &t);
        while(t--) {
            ans = 0;
            scanf("%d%d%lld", &n, &m, &c);
            for(int i = 0; i < 2; i++) 
            for(int j = 1; j < 2*n; j++) bs[i][j].clear();
            while(m--) {
                scanf("%d%d%lld", &u, &v, &p);
                p *= p;
                bs[0][u+v-1].push_back(P(u, p));
                bs[1][u-v+n].push_back(P(u, p));
            }
            for(int i = 0; i < 2; i++) 
            for(int j = 1; j < 2*n; j++) sort(bs[i][j].begin(), bs[i][j].end());
            
            for(int i = 0; i < 2; i++)
            for(int j = 1; j < 2*n; j++) {
                int len = bs[i][j].size();
                cnt = 0;
                for(int k = 0; k < len; k++) {
                    int x = bs[i][j][k].first;
                    ll p = bs[i][j][k].second;
                    _sort[cnt++] = -p-x;
                    _sort[cnt++] = p+c-x-1;
                }
                sort(_sort, _sort+cnt);
                cnt = unique(_sort, _sort+cnt)-_sort;
                for(int k = 1; k <= cnt; k++) tree[k] = 0;
                for(int k = 0; k < len; k++) {
                    int x = bs[i][j][k].first;
                    ll p = bs[i][j][k].second;
                    int id = cnt-(lower_bound(_sort, _sort+cnt, p+c-x-1)-_sort);
                    int tmp = sum(id);
                    ans = max(ans, tmp+1);
                    id = cnt-(lower_bound(_sort, _sort+cnt, -p-x)-_sort);
                    update(id, tmp+1);
                }
            }
            printf("%d
    ", ans);
        }
    } 
    View Code
  • 相关阅读:
    死锁
    钩子函数和回调函数的区别
    蓝绿部署、滚动发布、灰度发布的介绍以及最佳实践
    小公司的瓶颈
    Modbus协议详解
    windows+jenkin
    Java:简单的多态实例
    一、Kubernetes系列之介绍篇
    Shell脚本自动搭建ipsec环境
    Appium(1):安卓自动化环境搭建 + Android SDK + Appium 环境搭建
  • 原文地址:https://www.cnblogs.com/Pneuis/p/8900834.html
Copyright © 2011-2022 走看看