GYM 101147 F.Bishops Alliance(dp+BIT)

来源:互联网 发布:喝咖啡的利弊 知乎 编辑:程序博客网 时间:2024/04/30 10:47

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 111111typedef 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;}
0 0
原创粉丝点击