原题链接:http://codeforces.com/gym/101147/problem/F

题意:n*n的棋盘,给m个主教的坐标及其私有距离p,以及常数C,求位于同一对角线上满足条件:dist(i, j) >= p[i]^2 + p[j]^2 + C

的主教集合的元素个数最大值。

解题思路

上述条件可以等价为:

  d(j) - d(i) +1 >= p[i]^2 + p[j]^2 + C    // d(i) 为第i个主教相对于该对角线顶点的距离

  d(j) - p[j]^2 - C + 1>= d(i) + p[i]^2

设 f(i) = d(i) + p[i] ^2,  g(i) = d(i) - p[i]^2 - C + 1

下面考虑一条对角线,设 c[x]  为长度为x 的最后一个主教编号,例如c[len] = i  代表长度为len的防线最后一个主教编号为i。

(特别的,c[0] = 0, f(0) = -INF )

首先将该对角线上的主教按 d(i) 排序, len 为当前最大长度+1,依次查询每一个主教并同时更新最大长度, 伪代码如下:

  对当前查询的主教u

    j = lower_bound(c, c+len,u,cmp) - c

    if  j =len && g(u) >= f(c[j-1])

      c[len++] = u

    if  j != len &&  g(u) >= f(c[j-1])

      c[j] = u

注意: 数据范围为 LL

代码如下:

 #include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = +;
typedef long long LL;
#define INF 999999999999999999LL
vector<int> D1[*maxn];
vector<int> D2[*maxn]; int c[maxn];
int row[maxn], col[maxn], p[maxn];
int n, m, C;
//计算对角线编号
int dig_id1(int x, int y) {return x-y+n;}
int dig_id2(int x, int y) {return x+y;} int d1(int i) {return min(row[i], col[i]);}
int d2(int i) {return min(n-row[i]+, col[i]);} LL f1(int i) {return !i ? -INF : d1(i) + LL(p[i])*p[i];}
LL f2(int i) {return !i ? -INF : d2(i) + LL(p[i])*p[i];} LL g1(int i) {return d1(i) - LL(p[i])*p[i] - C + ;}
LL g2(int i) {return d2(i) - LL(p[i])*p[i] - C + ;} bool cmpd1(int i, int j) {return d1(i) < d1(j);}
bool cmpd2(int i, int j) {return d2(i) < d2(j);}
bool cmp1(const int& a,const int& b) {return f1(a) < f1(b);}
bool cmp2(const int& a,const int& b) {return f2(a) < f2(b);}
LL (*f[])(int) ={
f1,
f2
};
LL (*g[])(int) = {
g1,
g2
};
bool (*cmp[])(const int& ,const int& ) = {
cmp1,
cmp2
}; int cal(vector<int> &D,int flag) {
if(!D.size()) return ;
if(flag == ) sort(D.begin(), D.end(), cmpd1);
else sort(D.begin(), D.end(), cmpd2);
for(int i = ; i <= D.size(); i++) c[i] = ;
int len = ;
int j;
for(int i = ; i < D.size(); i++){
int u = D[i];
j = lower_bound(c, c+len, u, cmp[flag]) - c;
if(j == len && g[flag](u) >= f[flag](c[j-])) {
c[len++] = u;
}
if(j != len && g[flag](u) >= f[flag](c[j-])) {
c[j] = u;
}
}
return len - ;
}
#define fin stdin
int main() {
// FILE * fin;
// fin = fopen("bishops.in", "r");
int T;
fscanf(fin, "%d", &T);
while(T--) {
fscanf(fin, "%d%d%d", &n, &m, &C);
for(int i = ; i <= *n; i++) D1[i].clear();
for(int i = ; i <= *n; i++) D2[i].clear();
for(int i = ; i <= m; i++) {
fscanf(fin, "%d%d%d", &row[i], &col[i], &p[i]);
int id1 = dig_id1(row[i], col[i]);
int id2 = dig_id2(row[i], col[i]);
D1[id1].push_back(i);
D2[id2].push_back(i);
}
int ans = ;
for(int i = ; i <= *n; i++) {
ans = max(ans, cal(D1[i], ));
ans = max(ans, cal(D2[i], ));
}
printf("%d\n", ans);
}
return ;
}

Bishops Alliance—— 最大上升子序列的更多相关文章

  1. GYM - 101147 F.Bishops Alliance

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

  2. 【Mutual Training for Wannafly Union #1 】

    A.Phillip and Trains CodeForces 586D 题意:过隧道,每次人可以先向前一格,然后向上或向下或不动,然后车都向左2格.问能否到达隧道终点. 题解:dp,一开始s所在列如 ...

  3. 2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest (ECPC 16) 题解

    题目链接:http://codeforces.com/gym/101147 2017/8/27日训练赛,题目情况9/11,Rank 4/79. A. The game of Osho 题意:定义一个子 ...

  4. 2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest (ECPC 16)

    A.The game of Osho(sg函数+二项展开) 题意: 一共有G个子游戏,一个子游戏有Bi, Ni两个数字.两名玩家开始玩游戏,每名玩家从N中减去B的任意幂次的数,直到不能操作判定为输.问 ...

  5. 用python实现最长公共子序列算法(找到所有最长公共子串)

    软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...

  6. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  7. [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  8. [LeetCode] Is Subsequence 是子序列

    Given a string s and a string t, check if s is subsequence of t. You may assume that there is only l ...

  9. [LeetCode] Wiggle Subsequence 摆动子序列

    A sequence of numbers is called a wiggle sequence if the differences between successive numbers stri ...

随机推荐

  1. 【水滴石穿】rn_statusbar

    先放项目地址https://github.com/hezhii/rn_statusbar 来看一下效果 咩有感觉很怎么样,看代码 根入口文件 //index.js //看代码我们知道入口是app.js ...

  2. onethink二级导航调用

    <ul class="nav-main">//添加tree参数 <think:nav name="nav" tree="true&q ...

  3. Linux之Shell1

    1.输出命令:echo echo [选项] [输出内容] : -e  支持反斜线控制的字符转换.(类似于C语言的\) \\ 输出\本身 \t Tab键 \n 换行符 \f 换页符 ...  

  4. MAC+VS Code+C/C++调试配置

    目录 VS Code C/C++ 环境配置 添加工作区文件夹 Say Hello world 关于三个配置文件--Debug 原地址 VS Code C/C++ 环境配置 添加工作区文件夹 虽然代码能 ...

  5. Directx11教程(62) tessellation学习(4)

    原文:Directx11教程(62) tessellation学习(4)       现在看看四边形在不同tess factor时,四边形细分的细节,下图是tess factor1-8时候的细分.te ...

  6. objectarx之两条曲线最短距离

    double CCommonFuntion::GetLineDistance(AcDbObjectId& Line1, AcDbObjectId& Line2){ AcGeLineSe ...

  7. 微信小程序组件——详解wx:if elif else的用法

    背景 在学习微信小程序开发wxml页面时,需要使用if,else来判断组件是否进行展示,代码如下 <view wx:if="{{is_login==1}}">成功登录& ...

  8. 设备 VMnet0 上的网络桥接当前未在运行。

    早上,我打开我的虚拟机,却发现一个问题, 桥接网络怎么都连接不上. 报的是如下的错误 ------------------------------ 设备 VMnet0 上的网络桥接当前未在运行.该虚拟 ...

  9. hdu 1272 使用set和并查集

    http://acm.hdu.edu.cn/showproblem.php?pid=1272 这道题就是求图是不是连通无环,我觉得其实就是看看图是不是一棵最小生成树. 所以要是图满足条件,就必然有n个 ...

  10. gpu命令cuda命令

    # device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")os.envi ...