hdu6639:Faraway
theme:给定n与m,n代表方程个数,给定n个方程的xi,yi,ki,ti,求满足一下式子的xe,ye数目。1<=n<=10,1<=m<=1e9,0≤xi,yi≤m,2≤ki≤5,0≤ti<ki
solution:首先取绝对值,对xi,yi分别排序后有10*10个区域,每个确定的区域可以去掉绝对值(xi-xe+yi-ye)。
#include<bits/stdc++.h>
typedef long long ll;
#define inf 0x3f3f3f3f
using namespace std;
#define far(i,s,n) for(int i=s;i<n;++i)
int K=60;
int n;
struct _a
{
int k,t;
ll x,y;
}a[20];
ll X[20],Y[20];
bool check(ll x,ll y)
{
far(i,0,n)
{
if((abs(a[i].x-x)+abs(a[i].y-y))%a[i].k!=a[i].t)
return 0;
}
return 1;
}
ll cul(ll l,ll r)
{
r-=l+1;
if(r<0)
return 0;
return r/K+1;
}
int main()
{
int Case;
cin>>Case;
while(Case--)
{
ll m;
scanf("%d%lld",&n,&m);
far(i,0,n)
{
scanf("%lld%lld%d%d",&a[i].x,&a[i].y,&a[i].k,&a[i].t);
X[i+1]=a[i].x;
Y[i+1]=a[i].y;
}
ll ans=0;
X[n+1]=m+1;
Y[n+1]=m+1;
sort(X+1,X+n+2);
sort(Y+1,Y+n+2);
// int flag=0;
far(i,0,n+1)
if(X[i]<X[i+1])
far(j,0,n+1)
if(Y[j]<Y[j+1])
far(x,0,K)
far(y,0,K)
if(check(X[i]+x,Y[j]+y))
{
//++flag;
ans+=cul(X[i]+x,X[i+1])*cul(Y[j]+y,Y[j+1]);
//cout<<i<<" "<<j<<" "<<x<<" "<<y<<" "<<ans<<endl;
}
printf("%lld\n",ans);
}
}
hdu6635:Nonsense Time
theme:给定长度为n的序列,开始时所有元素都被冻住,即不可用,然后没次解冻某个元素Api,问当前可用元素的最长非降子序列长度为多少 ?1<=n<=50000,1<=Ai<=n,1<=pi<=n
solution:逆向考虑。先求出所有元素的最长非降子序列,然后倒序删除元素,若被删除的元素不是上一个最长非降子序列的关键元素,则长度不变,冻结它就行,否则冻住它,再算一遍最长非降子序列。用贪心+二分算最长非降子序列复杂度为o(nlogn),由于数据随机,所以LIS期望长度为sqrt(n),所以总时间复杂度为o(sqrt(n)*n*logn).
#include<bits/stdc++.h>
typedef long long LL;
#define inf 0x3f3f3f3f
using namespace std;
#define far(i,s,n) for(int i=s;i<n;++i)
int a[50050],fidx[50050];
int dp[50050],idx[50050],belong[50050];//dp存LIS元素,idx[i]表示a[i]能在dp中的位置下标,belong[i]标识a[i]是否为LIS关键元素
int ans[50050];
int n;
void Find()//找LIS
{
fill(dp,dp+n,inf);
fill(idx,idx+n,-1);
fill(belong,belong+n,0);
int maxl=0;
far(i,0,n)
{
if(a[i]!=inf)//表示a[i]没被冻住
{
int pos=lower_bound(dp,dp+n,a[i])-dp;
if(dp[pos]==inf)//a[i]比dp里所有元素都大,则把它加在后面
{
dp[pos]=a[i];
idx[i]=pos;
maxl = pos;
}
else
{
dp[pos]=a[i];//用较小的值替换
idx[i]=pos;
}
}
}
for(int i=n-1;i>=0;--i)//判断每个元素是否为关键元素,即每个该长度的LIS都有它
{
if(maxl<0)
break;
if(idx[i]==maxl)
{
belong[i]=1;
--maxl;
}
}
}
int main()
{
int Case;
cin>>Case;
while(Case--)
{
scanf("%d",&n);
far(i,0,n)
scanf("%d",&a[i]);
Find();
far(i,0,n)
{
scanf("%d",&fidx[i]);
--fidx[i];
}
for(int i=n-1;i>=0;--i)
{
ans[i]=lower_bound(dp,dp+n,inf)-dp;
if(belong[fidx[i]]==1)
{
a[fidx[i]]=inf;
Find();
}
else
a[fidx[i]]=inf;
}
far(i,0,n)
{
if(i==n-1)
printf("%d\n",ans[i]);
else
printf("%d ",ans[i]);
}
}
return 0;
}