HGOI 20190816 省常中互测8
Problem A
有两条以(0,0)为端点,分别经过(a,b),(c,d)的射线,你要求出夹在两条射线
中间,且距离(0,0)最近的点(x,y)对于$100\%$的数据满足$1 \leq T \leq 10^6 , 0 \leq a,b,c,d \leq 10^9$
Solution :
每次删除一个下面那条线斜率下取整这块三角形,然后将y坐标下移,
每一次分治下去,最后一定会存在一个时刻$(1,1)$合法,此时回溯回去即可。
由于分治前后,线段的相对位置不变,不会存在新的点更优,所以最后生成的答案一定是最优的。
每次查询的复杂度大约是$O(n)$的。
具体可以看下面$a = 2,b = 7,c = 4,d = 10$的求值方法。
# include <bits/stdc++.h>
# define int long long
using namespace std;
void work(int a,int b,int c,int d,int &x,int &y)
{
if (a<b&&c>d) { x=,y=; return; }
if (a*d>b*c) work(c,d,a,b,x,y);
else if (a>=b) work(b,a,d,c,y,x);
else {
int t=d/c;
work(a,b-t*a,c,d-t*c,x,y);
y+=t*x;
}
}
main()
{
int T; scanf("%lld",&T);
while (T--) {
int a,b,c,d; scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
int x,y; if (a*d>b*c) swap(a,c),swap(b,d);
work(a,b,c,d,x,y); printf("%lld %lld\n",x,y);
}
return ;
}
A.cpp
Problem B graph
给出$n$个点$m$条边的连通二分图$G$ ,给出$Q$组询问,每次求出$u,v$路径上(不一定是简单路径)的权值最大值。
一条路径的权值定义为,这条边经过所有节点的异或和,同一个点经过多次将会被计算多次。
对于$100\%$的数据满足$1 \leq n,m,Q\leq t\times 10^5$
Solution : 二分图性质题。
对于一个图$G$是二分图,满足一定是两个集合的点来考虑。
我们考虑$u - v$的一条路径,如果走简单路径就是$u \ xor \ v$的权值,如果走一个来回,那么就是$0$的权值。
所以,对于任意两点的任意一条路径,我们都可以考虑两个相邻点权值是否被异或到路径的答案中,可以同时取反。
对于询问中处在相同集合的两个点,路径经过点的数目一定是奇数,选择若干个点对翻转一定会造成奇数个节点的权值被选择(一个极端的例子就是什么节点都不翻转状态)
由于二分图的连通性,问题就等价于求在所给点集里找出奇数个点,使他们的异或和最大。
在询问中处在相异集合里的两个点,路径经过点的数目一定是偶数,选择若干个点对翻转一定会造成偶数个节点的权值被选择(一个极端的例子就是什么节点都不翻转状态)
由于二分图的连通性,问题就等价于求在所给点集里找出偶数个点,使他们的异或和最大。
在所给点集里找出偶数个点,使他们的异或和最大。这个问题可以将相邻两个点的点权插入到线性基里面,然后求出线性基中的最大值即可。
在所给点集里找出奇数个点,使他们的异或和最大。这个问题可以将相邻两个点的点权插入到线性基里面,强制地任意的取一个节点必须被异或,然后求出线性基中的最大值即可。
由于可以预处理这两个答案,最后询问的复杂度就是$O(1)$的,最终,本题的复杂度就是$O(n+Q)$的。
# include <bits/stdc++.h>
using namespace std;
const int N=5e5+;
struct rec{
int pre,to;
}a[N<<];
int head[N],n,m,q,val[N],tot,col[N];
void adde(int u,int v)
{
a[++tot].pre=head[u];
a[tot].to=v;
head[u]=tot;
}
struct Linear_Basis{
int d[];
Linear_Basis() {
memset(d,,sizeof(d));
}
void insert(int x) {
for (int i=;i>=;i--)
if (x&(<<i)) {
if (!d[i]) { d[i]=x; break;}
else x^=d[i];
}
}
int query(int ret) {
for (int i=;i>=;i--)
if ((ret^d[i])>ret) ret^=d[i];
return ret;
}
}B;
void dfs(int u,int c)
{
col[u]=c;
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (col[v]) continue;
dfs(v,-c);
}
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for (int i=;i<=n;i++) scanf("%d",&val[i]);
for (int i=;i<=m;i++) {
int u,v; scanf("%d%d",&u,&v);
adde(u,v); adde(v,u);
}
dfs(,);
for (int i=;i<n;i++) B.insert(val[i]^val[i+]);
int same = B.query(val[]);
int diff = B.query();
while (q--) {
int u,v;
scanf("%d%d",&u,&v);
if (col[u]==col[v]) printf("%d\n",same);
else printf("%d\n",diff);
}
return ;
}
B.cpp
Problem C geo
平面直角坐标系中有$n$个点$(x_i,y_i)$,求出有多少个二次函数$y = x^2 + bx +c$经过至少两个点,并且任何点都不在这个函数的上方。
对于$100\%$的数据,满足$n\leq 2\times 10^5$
Solution :
对于点$(x,y)$在$y = x^2 + bx + c$下方的条件是$x^2 + bx + c \geq y$
化简后就是$bx + c\geq y - x^2 $
对于所有的点$(x,y)$都是一定的,如果我们把每个点的坐标转化为$(x,y-x^2)$,
问题就转化为求一个一次函数$y = bx + c$使得这个一次函数至少经过两个点并且在所有点上方。
问题就等价于求出一个点集凸包的上部的边的条数。
即所有在左极点和右极点连线严格上方的点数+1。
复杂度就是$O(n)$的。
#include<bits/stdc++.h>
#define ll long long
#define inf (1e18)
using namespace std;
struct p{double x,y;}a[],s[],l,r;
ll n,k=,top=,ans;
double cross(p a,p b,p c){return(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);}
double dis(p a,p b){return sqrt((b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x));}
bool cmp(p x,p y)
{
double tmp=cross(a[],x,y);
return tmp>||(tmp==&&dis(a[],x)<dis(a[],y));
}
int main()
{
scanf("%lld",&n);
for(ll i=;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y),a[i].y-=a[i].x*a[i].x;
for(ll i=;i<=n;i++)if((a[k].y>a[i].y)||(a[k].y==a[i].y&&a[i].x<a[k].x))k=i;
swap(a[k],a[]),sort(a+,a++n,cmp),s[]=a[];
for(ll i=;i<=n;i++)
{
while(top>&&cross(s[top-],a[i],s[top])>=)top--;
s[++top]=a[i];
}
l={inf*1.0,inf*1.0},r={inf*-1.0,inf*-1.0};
for(ll i=;i<=top;i++)
{
if(s[i].x<l.x)l=s[i];else if(s[i].x==l.x&&s[i].y>l.y)l=s[i];
if(s[i].x>r.x)r=s[i];else if(s[i].x==r.x&&s[i].y>r.y)r=s[i];
}
for(ll i=;i<=top;i++)if(cross(l,r,s[i])>)ans++;
printf("%lld\n",ans+);
return ;
}
C.cpp
HGOI 20190816 省常中互测8的更多相关文章
- HGOI20190814 省常中互测7
Problem A 中间值 对于$2$个非严格单增序列$\{A_n\} , \{B_n\}$,维护下列两个操作: 1 x y z: (x=0)时将$A_y = z$ , (x=1)时将$B_y = z ...
- HGOI20190813 省常中互测6
Problem A 蛋糕 将$n \times m $大小的蛋糕切成每块为$1 \times 1$大小的$n\times m$块. 交换任意两块蛋糕的切割顺序的方案算作一种. 对于$100 \%$的数 ...
- HGOI20190811 省常中互测4
Problem A magic 给出一个字符串$S$,和数字$n$,要求构造长度为$n$只含有小写字母的字符串$T$, 使得在$T$中存在删除且仅删除一个子串使得$S=T$成立. 输出$T$的构造方案 ...
- HGOI20190810 省常中互测3
Problem A 夏洛特 若当前处在点$(x,y)$下一时刻可以向该点四周任意方向走动一步, 初始在$(0,0)$是否存在一条合法的路线满足下列$n$个限制: 每一个限制形如$t_i , x_i ...
- HGOI20190809 省常中互测2
Problem A 时之终结 构造一个含有$n$个节点的无重边无自环的有向图, 使得从$1$出发,每一次经过一条$(u,v) (u < v)$的边到达节点$n$的方案恰好有$y$种. 对于$10 ...
- HGOI20190808 省常中互测1
Problem A sum 给出$n$个元素的序列$\{a_i\}$,求出两个不相交连续子序列的最大元素和. 即对于$1 \leq A \leq B \leq C \leq D \leq n$最大化 ...
- HGOI20190812 省常中互测5
Task 1 辩论 有N 个参加辩论的候选人,每个人对这两个议题都有明确的态度,支持或反对.作为组织者,小D 认真研究了每个候选人,并给每个人评估了一个非负的活跃度,他想让活跃度之和尽可能大.选出的候 ...
- HGOI 20190821 慈溪一中互测
Problem A 给出一个$n$个点$m$条边的仙人掌图(每条边最多处于一个简单环中). 使用$c$种颜色对这张图中的顶点染色,使得每一条无向边连接的两个点颜色不同. 求染色的方案数,$mod \ ...
- 【2018集训队互测】【XSY3372】取石子
题目来源:2018集训队互测 Round17 T2 题意: 题解: 显然我是不可能想出来的……但是觉得这题题解太神了就来搬(chao)一下……Orzpyz! 显然不会无解…… 为了方便计算石子个数,在 ...
随机推荐
- Go语言流程控制中的break,continue和goto(七)
break(跳出循环) break用于跳出整个循环,如下: func main() { ;i<;i++{ { break } fmt.Println(i) } } // 0 1 2 3 代码里只 ...
- 关于Faster-RCNN训练细节
Faster RCNN训练: 四部训练法: Faster R-CNN,可以大致分为两个部分,一个是RPN网络,另一个是Fast R-CNN网络,前者是一种候选框(proposal)的推荐算法,而后者则 ...
- Java Web开发技术教程入门-数据库
补更:阅战阅勇第六天 今天阅读了这本书的第六章-访问数据.首先,这本书讲解的是MySql数据库,它是一个关系型数据库管理系统,是由瑞典MySqlAB公司开发,目前属于Oracle旗下公司.在web应用 ...
- Docker 构建私有镜像仓库
在使用Docker一段时间后,往往会发现手头积累了大量的自定义镜像文件,这些文件通过公有仓库进行管理并不方便,另外有时候只是希望在内部用户之间进行分享,不希望暴露出去.这种情况下,就有必要搭建一个本地 ...
- MySQL性能优化(二):优化数据库的设计
原文:MySQL性能优化(二):优化数据库的设计 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.n ...
- O012、Linux如何实现VLAN
参考https://www.cnblogs.com/CloudMan6/p/5313994.html LAN 表示 Local Area Network ,本地局域网,通常使用 Hub 或者 Sw ...
- 这38个小技巧告诉你如何快速学习MySQL数据库2
1.如何快速掌握MySQL? ⑴培养兴趣兴趣是最好的老师,不论学习什么知识,兴趣都可以极大地提高学习效率.当然学习MySQL 5.6也不例外.⑵夯实基础计算机领域的技术非常强调基础,刚开始学习可能还认 ...
- 淘宝flexible.js的使用
首先大家最关注的怎么使用,原理不原理是后面的事 比如设计稿量来的宽度是100px 那么我们布局的时候,就这么写{width:1.3333rem},1.3333rem是由100/75算出来的,以此类推2 ...
- js中 base64 转二进制
function base64toBlob(base64,type) { // 将base64转为Unicode规则编码 let bstr = atob(base64, type), n = bstr ...
- 7、Linux权限管理-基本权限
1.权限概述 1.1.什么是权限? 我们可以把它理解为操作系统对用户能够执行的功能所设立的限制,主要用于约束用户能对系统所做的操作,以及内容访问的范围,或者说,权限是指某个特定的用户具有特定的系统资源 ...