GYM - 101147 F.Bishops Alliance

题意:

  一个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\n", ans);
    }
} 
View Code

 

posted @ 2018-04-21 13:51  Pneuis  阅读(259)  评论(0编辑  收藏  举报