HDU 4716 A Computer Graphics Problem
水题。略
HDU 4717 The Moving Points
题目:给出n个点的起始位置以及速度矢量,问任意一个时刻使得最远的两点的距离最小。
分析:显然只有两点的话,答案满足三分性质。对于多个点,画个图分析一下,其实也满足三分性质。因此,先构造n*(n-1)/2个二次函数,于是三分枚举时间即可。
#include
#include
#include
#include
#include
#include
#include
HDU 4718 The LCIS on the Tree
我用的是树链剖分+线段树来写,发现在求lca合并时很难维护,改天用lct水掉算了 >.<
这题的简单版 hdu 3308 LCIS 线段树
待补。
HDU 4719 Oh My Holy FFF
题目大意:给出n个数b1...bn,现在需要划分集合,每个集合的元素不能超过L个,并且要求第i个集合的最后一个元素now大于第i-1个集合的最后一个元素pre。每个集合的价值为:now*now-pre。题目目标是:求max{ sigma(所有集合价值) }
分析:不难想出一个递推式:dp[i]表示当前i作为集合的最后一个元素的最优解。
dp[i] = max{ dp[j] + b[i]*b[i]-b[j] }。 0<=i-j<= L,b[j]
注意到b[i]是不变的,于是转移方程可以写成:
dp[i] = max{ b[i]*b[i] + (dp[j] -b[j]) }。 0<=i-j<= L,b[j]
如何在约束( 0<=i-j<= L,b[j]
这里可以用到单调队列,线段树维护一下即可。
具体实现(代码)献上我队友的代码吧 = =。
struct seg {
int l,r;
ll mx;
int mid() {
return l+r>>1;
};
} tree[maxn<<2];
void init_tree(int l,int r,int x)
{
tree[x].l=l,tree[x].r=r;
tree[x].mx=-1;
if(l==r)return;
int mid=l+r>>1;
init_tree(l,mid,lc(x));
init_tree(mid+1,r,rc(x));
}
void insert(int pos,int x,ll num)
{
if(tree[x].l==tree[x].r) {
tree[x].mx=num;
return;
}
int mid=tree[x].mid();
if(pos<=mid)insert(pos,lc(x),num);
else insert(pos,rc(x),num);
tree[x].mx=max(tree[lc(x)].mx,tree[rc(x)].mx);
}
ll query(int l,int r,int x)
{
if(l<=tree[x].l && tree[x].r<=r)
return tree[x].mx;
int mid=tree[x].mid();
ll res=-1;
if(l<=mid)res=max(res,query(l,r,lc(x)));
if(r>mid)res=max(res,query(l,r,rc(x)));
return res;
}
deque >q[maxn];
int t,n,m,cas;
ll a[maxn];
int main()
{
cin>>t;
while(t--) {
scanf("%d%d",&n,&m);
init_tree(0,100000,1);
for(int i=0; i<=100000; i++)
while(!q[i].empty())q[i].pop_front();
ll ans=-1;
for(int i=1; i<=n; i++)
scanf("%I64d",&a[i]);
for(int i=1; i<=n; i++) {
ll res=query(0,a[i]-1,1);
if (i <= m && res==-1)res=0;
if(res!=-1) {
res+=a[i]*a[i];
if(i==n)ans=res;
while(!q[a[i]].empty() && q[a[i]].back().first<=res-a[i])
q[a[i]].pop_back();
q[a[i]].push_back(mp(res-a[i],i));
if(q[a[i]].front().second==i)
insert(a[i],1,q[a[i]].front().first);
}
if(i>m) {
insert(a[i-m],1,-1);
if(q[a[i-m]].size() && q[a[i-m]].front().second==i-m)
q[a[i-m]].pop_front();
if(!q[a[i-m]].empty())
insert(a[i-m],1,q[a[i-m]].front().first);
}
}
if(ans!=-1)printf("Case #%d: %I64d\n",++cas,ans);
else printf("Case #%d: No solution\n",++cas);
}
}
HDU 4720 Naive and Silly Muggles
注意到不一定是外接圆,如果是钝角三角形时,最长边即为直径。
#include
#include
HDU 4721 Food and Productivity
待补
HDU 4722 Good Numbers
数位DP
#include
#include
#include
#include
#include
#include
#include
HDU 4723 How Long Do You Have to Draw
怎么我感觉这题不难,难道我打开的方式不对?可惜比赛时没看题。。。
给出n个纵坐标为a的点,c1
给出m个纵坐标为b的点,d1
问如何对上下点进行连边,使得三角形最多,并且边不能相交。
分析:对于下图进行分析讨论即可。
如果c点已经到了最后,则:c点连剩下的d点
如果d点已经到了最后,则:d点连剩下的c点
如果c,d后面还有,有两种情况:
1.为c1,d1,d2在c1,c2中线左边,则c1连d1,d后移
2.为c1,d2,d3在c1,c2中线右边,则c1连d1,判断c1d3,c2d2的距离,根据那个更优移动哪个点即可。

#include
#include
HDU 4724 If You Know This,You Must Have NO GF
待补
HDU 4725 The Shortest Path in Nya Graph
使用堆维护dijkstra的算法,每次从堆中取出一个节点,如果该节点所在的层没被标记,更新相邻两层,标记上(因为每次都从堆中去最小值,因此当前层的最优值必定是第一次访问时所得,进而更新其他的层)。至于边的松弛,跟普通的dijkstra一样。详细看代码。
#include
#include
HDU 4726 Kia's Calculation
贪心。第一位想清楚了,后面的直接贪心。略
HDU 4727 The Number Off of FFF
水题。注意全对时输出1。略