Bishops Alliance—— 最大上升子序列
原题链接: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
代码如下:
1 #include <cstring> 2 #include <cstdio> 3 #include <algorithm> 4 #include <vector> 5 using namespace std; 6 const int maxn = 100000+10; 7 typedef long long LL; 8 #define INF 999999999999999999LL 9 vector<int> D1[2*maxn]; 10 vector<int> D2[2*maxn]; 11 12 int c[maxn]; 13 int row[maxn], col[maxn], p[maxn]; 14 int n, m, C; 15 //计算对角线编号 16 int dig_id1(int x, int y) {return x-y+n;} 17 int dig_id2(int x, int y) {return x+y;} 18 19 int d1(int i) {return min(row[i], col[i]);} 20 int d2(int i) {return min(n-row[i]+1, col[i]);} 21 22 LL f1(int i) {return !i ? -INF : d1(i) + LL(p[i])*p[i];} 23 LL f2(int i) {return !i ? -INF : d2(i) + LL(p[i])*p[i];} 24 25 LL g1(int i) {return d1(i) - LL(p[i])*p[i] - C + 1;} 26 LL g2(int i) {return d2(i) - LL(p[i])*p[i] - C + 1;} 27 28 bool cmpd1(int i, int j) {return d1(i) < d1(j);} 29 bool cmpd2(int i, int j) {return d2(i) < d2(j);} 30 bool cmp1(const int& a,const int& b) {return f1(a) < f1(b);} 31 bool cmp2(const int& a,const int& b) {return f2(a) < f2(b);} 32 LL (*f[])(int) ={ 33 f1, 34 f2 35 }; 36 LL (*g[])(int) = { 37 g1, 38 g2 39 }; 40 bool (*cmp[])(const int& ,const int& ) = { 41 cmp1, 42 cmp2 43 }; 44 45 int cal(vector<int> &D,int flag) { 46 if(!D.size()) return 0; 47 if(flag == 0) sort(D.begin(), D.end(), cmpd1); 48 else sort(D.begin(), D.end(), cmpd2); 49 for(int i = 0; i <= D.size(); i++) c[i] = 0; 50 int len = 1; 51 int j; 52 for(int i = 0; i < D.size(); i++){ 53 int u = D[i]; 54 j = lower_bound(c, c+len, u, cmp[flag]) - c; 55 if(j == len && g[flag](u) >= f[flag](c[j-1])) { 56 c[len++] = u; 57 } 58 if(j != len && g[flag](u) >= f[flag](c[j-1])) { 59 c[j] = u; 60 } 61 } 62 return len - 1; 63 } 64 #define fin stdin 65 int main() { 66 // FILE * fin; 67 // fin = fopen("bishops.in", "r"); 68 int T; 69 fscanf(fin, "%d", &T); 70 while(T--) { 71 fscanf(fin, "%d%d%d", &n, &m, &C); 72 for(int i = 0; i <= 2*n; i++) D1[i].clear(); 73 for(int i = 0; i <= 2*n; i++) D2[i].clear(); 74 for(int i = 1; i <= m; i++) { 75 fscanf(fin, "%d%d%d", &row[i], &col[i], &p[i]); 76 int id1 = dig_id1(row[i], col[i]); 77 int id2 = dig_id2(row[i], col[i]); 78 D1[id1].push_back(i); 79 D2[id2].push_back(i); 80 } 81 int ans = 0; 82 for(int i = 0; i <= 2*n; i++) { 83 ans = max(ans, cal(D1[i], 0)); 84 ans = max(ans, cal(D2[i], 1)); 85 } 86 printf("%d\n", ans); 87 } 88 return 0; 89 }