2 3 2 0 0 0 1 0 0 1 1 5 3 0 0 0 1 0 0 0 1 0 2 2 3 3 3
2 1 3 2HintIn the first case, RD can shoot the second ball at first and hit the third ball indirectly. In the second case, RD can shoot the second or the third ball initially and hit the fourth ball as well as the fifth ball. Two schemes are both the best.
#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=100010;
const int mod=1<<30;
typedef long long ll;
struct node
{
int x,y,z;
inline bool operator <(const node& tt) const
{
if(x!=tt.x)
return x<tt.x;
if(y!=tt.y)
return y<tt.y;
return z<tt.z;
}
} po[maxn];
int dp[maxn],sy[maxn],sz[maxn],mv[maxn],ans;
int tmp[maxn<<1],ty[maxn],ptr;
ll num[maxn],nv[maxn],ansn;
bool cmp(int a,int b)//注意y必须这么排.不然可能出现y相等的时候i+1排到i前面的情况.
{
if(po[a].y!=po[b].y)
return po[a].y<po[b].y;
return a<b;
}
void update(int x,int v,ll d,int mn)
{
for(int i=x;i<=mn;i+=i&-i)
{
if(v>mv[i])
mv[i]=v,nv[i]=d;
else if(v==mv[i])
nv[i]+=d;
}
}
int qu(int x,ll &nn)
{
int ret=0;
for(int i=x;i>0;i-=i&-i)
{
if(ret<mv[i])
ret=mv[i],nn=nv[i];
else if(mv[i]==ret)
nn+=nv[i];
}
return ret;
}
void solve(int l,int r)
{
if(l==r)
{
if(dp[l]>ans)
ans=dp[l],ansn=num[l];
else if(dp[l]==ans)
ansn+=num[l];
sz[l]=po[l].z;
return;
}
int mid=(l+r)>>1,le=l,ri=mid+1,len=r-l+1,ml=mid-l+1,lim,h,i;
memmove(tmp+ptr,sy+l,len*sizeof(int));
for(i=0;i<len;i++)
if(tmp[ptr+i]<=mid)//直接把排好的序划分下去就行了。
sy[le++]=tmp[ptr+i];
else
sy[ri++]=tmp[ptr+i];
ptr+=len;
solve(l,mid);
lim=ptr,ptr-=len;
for(i=1;i<=ml;i++)
mv[i]=0;
for(i=ptr;i<lim;i++)
{
if(tmp[i]<=mid)
{
h=lower_bound(sz+l,sz+l+ml,po[tmp[i]].z)-(sz+l)+1;
update(h,dp[tmp[i]],num[tmp[i]],ml);
continue;
}
h=lower_bound(sz+l,sz+l+ml,po[tmp[i]].z)-(sz+l);
if(h>=ml||sz[l+h]>po[tmp[i]].z)
h--;
if(h>=0)
{
ll cc=0;
int tt=qu(h+1,cc)+1;
if(tt>dp[tmp[i]])
dp[tmp[i]]=tt,num[tmp[i]]=cc;
else if(tt==dp[tmp[i]]&&tt!=1)
num[tmp[i]]+=cc;
}
}
solve(mid+1,r);
merge(sz+l,sz+l+ml,sz+l+ml,sz+l+len,ty);
memmove(sz+l,ty,len*sizeof(int));
}
int main()
{
int t,n,i;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d%d%d",&po[i].x,&po[i].y,&po[i].z);
ansn=ptr=ans=0;
sort(po+1,po+n+1);
for(i=1;i<=n;i++)
sy[i]=i,dp[i]=1,num[i]=1;
sort(sy+1,sy+n+1,cmp);
solve(1,n);
printf("%d %I64d\n",ans,ansn%mod);
}
return 0;
}
/*
送一组数据。网上好多代码都过不了这组。就是因为排序y的时候i+1排到i前面去了。导致少更新很多
杭电数据比较水就水过去了。
1
17
2 0 0
2 1 1
1 2 1
1 0 0
0 0 1
0 2 0
0 2 2
0 1 1
2 0 1
1 2 2
0 1 0
2 0 2
2 2 2
0 1 2
1 0 2
1 1 1
0 0 2
*/
hdu 4742 Pinball Game 3D(三维LIS&cdq分治&BIT维护最值)
原文:http://blog.csdn.net/bossup/article/details/39902415