Description
一个棋盘,上面有一些棋子,第i个棋子有一个p[i]值,现在要选择在同一条对角线上的某些棋子,使得对任意两个棋子i和j,i到j之间所隔格子数不小于pi^2+pj^2+c,其中c是一给定常数,问最多可以选多少个棋子
Input
第一行一整数T表示用例组数,每组用例首先输入三个整数n,m,c分别表示棋盘规格,棋子数量和常数c,之后m行每行三个整数xi,yi,pi表示第i个棋子的位置和p值(1<=n<=1e5,1<=m<=1e5,0<=c<=1e5,1<=xi,yi,pi<=n)
Output
输出最多选多少棋子
Sample Input
1
8 5 2
7 7 1
4 4 1
3 5 1
2 6 2
4 8 1
Sample Output
2
Solution
考虑每一条对角线可以选多少棋子,取最大值即为答案,先考虑一条对角线上i,j,k三个棋子(i < j < k),如果i-j+1>=pi*pi+pj*pj+c,j-k+1>=pj*pj+pk*pk+c,那么i-k+1>=pi*pi+2*pj*pj+pk*pk+2*c-1>=pi*pi+pk*pk+c,说明该种关系具有传递性,那么就不需要两两去考虑所选棋子,只需要从小大到按顺序来即可,以dp[i]表示该条对角线上前i个中最多能选的棋子个数,那么dp[i]=max(dp[j])+1,其中j需满足i-j+1>=pi*pi+pj*pj+c,即-j+pj*pj>=pi*pi-i+c-1,把所有的-i-pi*pi和i+pi*pi+c-1存起来离散化一下,用BIT维护前缀dp[i]的最大值,离散化的值代表在BIT中要插入的位置,处理到一个i时,查询i+pi*pi+c-1离散化后的值在BIT中对应的位置的前缀最大值即为max(dp[j]),加一就是dp[i]的值,再在-i-pi*pi离散化后的值对应的位置处插入dp[i]的值即可,实时维护dp[i]的最大值ans即为最终答案
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 111111
typedef pair<int,ll>P;
vector<P>v[2][2*maxn];
int T,n,m,c;
ll h[2*maxn];
struct BIT
{
#define lowbit(x) (x&(-x))
ll b[2*maxn];
int m;
void init(int n)
{
m=n;
for(int i=1;i<=n;i++)b[i]=0;
}
void update(int x,ll v)
{
while(x<=m)b[x]=max(b[x],v),x+=lowbit(x);
}
ll query(int x)
{
ll ans=b[x];
while(x)ans=max(ans,b[x]),x-=lowbit(x);
return ans;
}
}bit;
int main()
{
freopen("bishops.in","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&c);
for(int i=0;i<2;i++)
for(int j=1;j<2*n;j++)
v[i][j].clear();
while(m--)
{
int x,y,p;
scanf("%d%d%d",&x,&y,&p);
v[0][x+y-1].push_back(P(x,1ll*p*p));
v[1][x-y+n].push_back(P(x,1ll*p*p));
}
int ans=0;
for(int i=0;i<2;i++)
for(int j=1;j<2*n;j++)
{
sort(v[i][j].begin(),v[i][j].end());
int res=0;
for(int k=0;k<v[i][j].size();k++)
{
int x=v[i][j][k].first;
ll p=v[i][j][k].second;
h[res++]=-p-x,h[res++]=p-x+c-1;
}
sort(h,h+res);
res=unique(h,h+res)-h;
bit.init(res);
for(int k=0;k<v[i][j].size();k++)
{
int x=v[i][j][k].first;
ll p=v[i][j][k].second;
int pos=lower_bound(h,h+res,p-x+c-1)-h;
pos=res-pos;
int num=bit.query(pos);
ans=max(ans,num+1);
pos=lower_bound(h,h+res,-p-x)-h;
pos=res-pos;
bit.update(pos,num+1);
}
}
printf("%d\n",ans);
}
return 0;
}