杭电多校第一场属实恐怖,我连补题的冲动都莫得了。
本来还想说按去年的经验来说,杭电是要比牛客稍微友好那么一丢丢的吧。结果当场打脸,签到题来了个最短路*2+网络流,这谁顶得住啊。
所以这两天都没在补这场,感觉不太适合我 ······ 今天先更新一下好了,这场就先这样罢,太难了。
以下题解包括:
\[1002【HDU-6579】 \\ 1004【HDU-6581】 \\ 1005【HDU-6582】 \\ 1009【HDU-6586】 \\ 1013【HDU-6590】\]
【1002】 线性基 HDU-6579 Operation
这场之前我是没学过线性基的(其实是刚了两个小时多的签到题没空看)后面听完题目确定是线性基然后怎么算复杂度都算不对,根本没想到还能先求前缀...好吧太菜了
http://acm.hdu.edu.cn/showproblem.php?pid=6579
给定 n 个数的序列和 m 次询问(\(\sum n \leq 10^6,\sum m \leq 10^6, 0\leq x \leq 2^{30}\))。有 2 种操作,\(0 \ l \ r\) 表示查询区间 \([l, r]\) 里(选择一些数的)最大异或和;\(1 \ x\) 表示把数值 \(x\) 插入到序列末尾。查询过程强制在线。
对于线性基来说,需要将出现在序列靠右的数尽可能地放在高位(在插入新数字的时候,需要记录对应位置上数字出现的位置,在找到可插入的位置时,如果新数字比位置上的原数字更靠右,就将原数字放到低位)。
另外还需要两个数组: \(cnt\_d[i][j]\) 保存 \([1,i]\) 区间第 \(j\) 位线性基的值;\(cnt\_pos[i][j]\) 保存 \([1,i]\) 区间第 \(j\) 位线性基的位置)。
对于给定的 \([l,r]\),从最高位开始,找出 \(cnt\_pos[r][j] \geq l \ \&\& \ (ans \bigoplus cnt\_d[r][j]) > ans\) 的值异或起来就是答案。
ps:本题和 CF1100F 基本一致,除了 CF1100F 没有插入操作。
#include
【1004】 数学 HDU-6581 Vacation
与其说是数学题,还不如说是思维题... 题目很快就读完了,然后所有人被我一说就全怕了,结果看完题解都傻了,当然包括我...
http://acm.hdu.edu.cn/showproblem.php?pid=6581
给定 n+1 辆车,第 0 辆是主角车。给定每辆车车头距离终点线的距离 \(s_i\),车身长度 \(l_i\),最高速度 \(v_i\)。距离终点远的车不能超车,如果后车最高速度大于前车,那么他会跟随前车的速度。问主角车车头需要多久能抵达终点线。
比赛的时候想法实在是太复杂了,复杂到我都没想到自己能想到那些奇奇gaygay的情况。
我们只需要分两种情况考虑:
- 对于主角车 0,如果将它前面的车全部去掉,那么可以得到最短用时(\(s_0 /v_0\))
- 对于其他车,它的车尾越过停止线时所跑的距离总是 \(sum_i = s_i + \sum^{i}_{j=1}l_j\),那么主角车花费的时间最短理论时间可能是 \(sum_i / v_i\)
对于以上两种情况,我们只需要对每种情况取最大值即可,因为最大值是最坏情况,也是满足条件的唯一可能。
#include
【1005】 最短路+网络流 HDU-6582 Path
最短路+网络流的签到题,群友们tql,人均网络流。
我收获颇丰,成功发现自己的板子 spfa 和 dinic 全是错的...
http://acm.hdu.edu.cn/showproblem.php?pid=6582
给定 n 个节点和 m 条边,边是单向边,每条边都有权值。问要让图的最短路变大的情况下,最少需要删掉多少权值的边。输出最小权值。
正向建图跑最短路,再反向建图跑最短路,这样可以求出每个点对于 起点 和 终点 的距离,然后可以判断那些边是可能存在最短路上的。然后把这些边再建一张图跑网络流即可。
如果读懂题了,其实就是模板题,主要是代码量大...
#include
【1009】 模拟+单调栈 HDU-6586 String
我发现今年怎么全是单调队列单调栈,我人傻了,今天会明天不会...
http://acm.hdu.edu.cn/showproblem.php?pid=6586
给定一个由小写字母构成的字符串,从中选择一个长度为 k 的子序列,要求26种字母的出现次数满足下面所给的 \([l, r]\) (最少出现次数和最多出现次数),并且字典序最小。
字典序最小用单调栈维护,然后就是模拟模拟大模拟...
#include
【1013】 凸包相交判定 HDU-6590 Code
题面极长,题意极简,代码...又臭又长
http://acm.hdu.edu.cn/showproblem.php?pid=6590
其实就是给定两种点,问你能不能画一条直线把这两种点分开。
对于这种题我是莫得办法的...我只能把他当做模板记下来...就这样
以下代码来自:https://blog.csdn.net/jerry99s/article/details/97269795
别问我为什么不自己做..因为太懒了其实是看了一下午假题解心态崩了。
#include
using namespace std;
typedef long long llong;
const int tmax=105;
struct Point{
llong x,y;
Point(llong x=0,llong y=0):x(x),y(y){}
Point operator +(Point p)
{
return Point(x+p.x,y+p.y);
}
Point operator -(Point p)
{
return Point(x-p.x,y-p.y);
}
bool operator<(Point p)
{
return x!=p.x?x=2&&cross(aim[m]-aim[m-1],P[i]-aim[m-1])<=0) m--;
aim[++m]=P[i];
}
int k=m;
for(i=n;i>=1;i--)
{
while(m>k&&cross(aim[m]-aim[m-1],P[i]-aim[m-1])<=0) m--;
aim[++m]=P[i];
}
return m;
}
bool check(Point A,Point *p,int n)
{
int l=1,r=n-2,mid;
while(l<=r)
{
mid=(l+r)>>1;
double a1=cross(p[mid]-p[0],A-p[0]);
double a2=cross(p[mid+1]-p[0],A-p[0]);
if(a1>=0&&a2<=0)
{
if(cross(p[mid+1]-p[mid],A-p[mid])>=0) return true;
return false;
}
else if(a1<0)
r=mid-1;
else l=mid+1;
}
return false;
}
int main()
{
int T,i,n,kind,num0[2],num1[2];
Point data[2][tmax],aim[2][tmax],tmp;
scanf("%d",&T);
while(T--)
{
num0[0]=num0[1]=num1[0]=num1[1]=0;
memset(data,0,sizeof(data));
memset(aim,0,sizeof(aim));
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%lld%lld%d",&tmp.x,&tmp.y,&kind);
if(kind==1) data[1][++num1[0]]=tmp;
else data[0][++num0[0]]=tmp;
}
num0[1]=convexHull(data[0],num0[0],aim[0]);
num1[1]=convexHull(data[1],num1[0],aim[1]);
bool ok=false;
for(i=1;i<=num0[1];i++)
ok|=check(aim[0][i],aim[1]+1,num1[1]);
for(i=1;i<=num1[1];i++)
ok|=check(aim[1][i],aim[0]+1,num0[1]);
if(!ok) printf("Successful!\n");
else printf("Infinite loop!\n");
}
return 0;
}