这是一道交互题。
给定平面上的 n 个点,第 i+1 个点为 (xi,yi),初始值为 di,0≤i<n;
你需要按顺序进行 m 次操作,所有操作在一开始已知;
第 j+1 次操作给出三个数 aj,bj,cj,以及 oj,表示半平面 ajx+bjy<cj,0≤j<m;
你需要按顺序执行:
首先令 sj=ϵD,然后对每个满足 ajxi+bjyi<cj 的 i,先将 sj 修改为 sj+di,后将 di 修改为 oj⋅di;
完成这些修改后,就得到了这次操作的答案 sj;
其中 di 属于抽象的数据类型 D,oj 属于抽象的数据类型 O;
D 上定义了抽象的运算 +:D×D→D;
D,O 上定义了抽象的运算 ⋅:O×D→D;
O 上定义了抽象的运算 ⋅:O×O→O;
ϵD 是 D 中的一个特殊的元素,称为单位元;
ϵO 是 O 中的一个特殊的元素,称为单位元;
这些操作满足性质:
对任意 a,b,c∈D,有 a+b=b+a,(a+b)+c=a+(b+c),a+ϵD=ϵD+a=a;
对任意 u,v,w∈O,有(u⋅v)⋅w=u⋅(v⋅w),u⋅ϵO=ϵO⋅u=u;
对任意 u,v∈O,a,b∈D,有(u⋅v)⋅a=u⋅(v⋅a),u⋅(a+b)=(u⋅a)+(u⋅b),ϵO⋅a=a,u⋅ϵD=ϵD;
执行每次 + 或 ⋅ 运算有一定的代价,具体地,在计算 a+b 或 a⋅b 时如果 a,b 都不是 ϵD 或 ϵO,则代价为1,否则代价为0。你需要保证每个答案正确,且总代价不能超过当前子任务的代价上限。
输入格式
下发的交互库以如下格式读取输入数据:
- 第一行:n
- 接下来 n 行:xiyidi(di 由两个整数表示)
- 第 n+2 行:m
- 接下来 m 行:aibicioi(oi 由4个整数表示)
D 中的元素是 2×1 的矩阵,O 中元素是 2×2 的矩阵,矩阵中的元素是对 232 取模的整数;
+ 对应矩阵加法,⋅ 对应矩阵乘法,具体可以参考下发的交互库的实现;
实际评测环境中输入输出格式以及 D,O 等可能有不同的定义;
输出格式
下发的交互库以如下格式打印你的答案:
- 前 m 行:si,由两个整数表示
- 第 m+1 行:总代价
实现细节
你必须引用 hpmq.h
头文件。
头文件中定义了数据类型 Data
(D)和 Operation
(O),你可以使用以下已定义的成员函数对类型为 Data
和 Operation
的数据进行操作:
void Data::add_eq(const Data &a)
w.add(a)
计算 w+a,并将结果保存在 w,每次调用的代价在 w,a 都不是单位元时为1,否则为0;
void Data::add(const Data &a,const Data &b)
w.add(a,b)
计算 a+b,并将结果保存在 w,每次调用的代价在 a,b 都不是单位元时为1,否则为0;
void Data::clr()
w.clr()
可以将 ϵD 保存在 w,每次调用的代价为0;
void Data::print()const
w.print()
可以将 w 作为一次操作的答案,每次调用的代价为0,这个函数需要被调用恰好 m 次,依次对应每次操作的答案;
bool Data::empty()const
w.empty()
判断 w 是否为ϵD,若是则返回 true,否则返回 false,每次调用的代价为0;
void Operation::apply(Data &a)const
w.apply(a)
计算 w⋅a,并将结果保存在 a,每次调用的代价在 w,a 都不是单位元时为1,否则为0;
void Operation::apply(Operation &u)const
w.apply(u)
计算 w⋅u,并将结果保存在 u,每次调用的代价在 w,u 都不是单位元时为1,否则为0;
void Operation::clr()
w.print()
可以将 ϵO 存储在 w,每次调用的代价为0;
bool Operation::empty()const
w.empty()
判断 w 是否为ϵO,若是则返回 true,否则返回 false,每次调用的代价为0;
另外,你还可以使用 Data
或 Operation
类型的赋值运算符、拷贝构造函数或无参构造函数,以 Data
类型为例:
w=u
可以将 u 复制一份存储在 w,每次调用的代价为0;
Data w(u);
或 Data w=u;
可以将 u 复制一份存储在新定义的 w,每次调用的代价为0;
Data w;
可以将 ϵD 存储在新定义的 w,代价为0;
Operation w;
可以将 ϵO 存储在新定义的 w,代价为0;
除了以上描述的对 Data
或 Operation
的操作外,其余操作根据情况可能被视为攻击评测系统。
sizeof(Data)
和 sizeof(Operation)
都不超过64,此外交互库还需要不超过64MB的空间。时间和空间限制包括交互库使用的时间和空间。仅使用赋值、构造函数、apply
和 add
就可以写出正确的程序,其它函数可能可以提供便利。
你需要实现以下函数:
void solve(
const int n,
const int m,
const int *x,
const int *y,
const Data *d,
const int *a,
const int *b,
const int *c,
const Operation *o)
- n:点的个数;
- x,y,d:大小为 n 的数组,其中 (xi,yi) 为第 i+1 个点的坐标,这个点的初始值为 di;
- m:操作的个数;
- a,b,c,o:大小为 m 的数组,其中第 i+1 次操作的范围为半平面 aix+biy<ci,修改操作为 oi;
限制与约定
对于所有数据,满足:
|xi|≤106,|yi|≤106;
|ai|≤103,|bi|≤103,bi≠0,|ci|≤106;
xi,yi,ai,bi,ci 为整数;
对任意 i,j,有 aixj+biyj≠ci,即不存在点在直线上的情况;
对任意 i≠j,有 (aibi,cibi)≠(ajbj,cjbj),即不存在重合的直线;
数据被分为8个子任务,每个子任务有固定的 n,m 和允许的代价上限,每个子任务可能依赖其它子任务,只有通过一个子任务和其依赖的子任务的所有测试点才能获得这个子任务的分值;
子任务 | n | m | 代价上限 | 分值 | 依赖 |
---|---|---|---|---|---|
1 | 2×104 | 103 | 4×107 | 5 | |
2 | 2×104 | 103 | 8×105 | 15 | 1 |
3 | 2×105 | 102 | 4×107 | 5 | |
4 | 2×105 | 102 | 1.25×106 | 15 | 3 |
5 | 216 | 104 | 8×107 | 20 | |
6 | 2×105 | 104 | 2.5×107 | 10 | |
7 | 2×105 | 104 | 1.25×108 | 15 | |
8 | 2×105 | 104 | 2.5×107 | 15 | 1~7 |
子任务5满足特殊限制:−27≤xi<27,−27≤yi<27,对任意 i≠j,有 (xi,yi)≠(xj,yj),即不存在重合的点;
子任务6满足特殊限制:对 0≤i<n,0≤j<m,xi=0,yi=2i,aj=0,|bj|=1;