A.Alarm Clock
P某需要睡觉a分钟,他只有听到闹钟才会起床,他先睡,他所设定的第一个闹钟将会在b分钟后响起,然后他将闹钟重置,设定为c分钟后响,然后需要花费d分钟才能入睡
LL cnt = (a - b + (c - d) - 1) / (c - d);
int main(){
int t;
for(RD(t); t; t--){
LL a, b, c, d; RDD(a, b);RDD(c, d);
if (b >= a) OT(b);
else{
if (c <= d){
OT(-1);
}
else{
LL las = a - b;
LL cnt = (las + (c - d) - 1) / (c - d);
OT(b + cnt * c);
}
}
}
}
B.Ternary String
给你一段序列,里面只包含’1’‘2’'3’字符,要求你求解包含这三个字符的最短连续子列
分别记录这三个字符的最新位置,记录长度,并不断更新,确保最短
int main(){
int t;RD(t);
while(t--){
string s;
cin >> s;
int o = -1, t = -1, th = -1;
int len = maxn;
for(int i = 0;i < s.size(); i++){
if (s[i] == '1') o = i;
else if (s[i] == '2') t = i;
else if (s[i] == '3') th = i;
if (o != -1 && t != -1 && th != -1)
len = min(max(o, t, th) - min(o, t, th) + 1, len);
}
if(len == maxn) cout << "0" << '\n';
else cout << len << '\n';
}
}
C1.Simple Polygon Embedding
求解正2*n边型的最小外接正方形(n为偶数)
由于n是偶数,所以在正2n边形中当中是会存在一个对称的情况
拿正2*4边形举个例子,你会发现我们EF和AB是平行的,同理GH//DC
这几个边延长便是我们的外接正方形了,由于对称性,所以可以旋转,但是结果都一样
如何求解呢,做个EF的中垂线,将角度设置为α
我们需要把角度转化为弧度才能在math库的sin函数中使用
公式: rad = α * PI / 180
int main(){
//cout << PI << '/n';
int t;
for(RD(t); t; t--){
int n; RD(n);
DB xt = 360 / (DB)(2 * n) / 2;
DB rad = xt * (PI / 180);
DB ans = 1 / tan(rad);
printf("%.10f\n", ans);
}
}
C2.Not So Simple Polygon Embedding
求解正2*n边型的最小外接正方形(n为奇数)
与C1的差别就是差在n为奇数这一点上面,对于原先存在的对称行就需要重新考虑了。
奇数的情况我们换个方法,不如先把外接的正方形先画出来
然后分角度(我们就以n最小的时候为例进行画图n=3)
3.画圆求解正2n边形剩下的点,由于我们已经设定好了,外接正方形,所以正2n边边形必然不能超过正方形的,这也就是为什么圆的半径我们选择的是OJ而不是OC(圆心为O)
4.连接各点,现在我们很清楚,实际上我们要求的就是DF+FC
int main(){
int _;
for(scanf("%d", &_); _;_--){
int n; RD(n);
printf("%.10f\n", cos(PI/(4*n))/sin(PI/(2*n)));
}
}
D. Multiset
给你一段长度为 n n n的序列 a 1 , a 2 , a 3... a n a1,a2,a3...an a1,a2,a3...an,对序列进行 q q q次操作,分别为 k 1 , k 2 , k 3... k n k1,k2,k3...kn k1,k2,k3...kn,
存在两种解法
1.编写数据结构,模拟解决问题,
树状数组能解决的问题,线段树都能解决,但是树状数组的代码量小,好写,我对线段树的代码进行了测试,个人认为本题是不太适合线段树的,如果不加上快读的话,代码是会TLE在第五点
我们只需要找到一个属于集合的数字。
例如,让我们找到最小的元素。我们可以通过二分搜索来做到这一点,如下所示:让我们为给定元素编写一个函数X,告诉元素数不大于 X在生成的多集中。要实现它,请使用所有元素≤ X 难以区分,所有要素 > x 也是无法区分的,因此只需两个计数器即可维护多集。
好的,此功能有什么帮助?所得多重集中的最小值为最小值X 这样该函数将为其返回非零值,并且由于该函数是单调的,因此我们可以使用二进制搜索找到答案。
//线段树
const int maxn = 1e6 + 5;
int sumt[maxn<<2];
#define lson p<<1
#define rson p<<1|1
void ins(int p,int l,int r,int k)
{
if(l == r) { sumt[p]++; return ;}
int mid = l + r >> 1;
if(k <= mid)
ins(lson, l, mid, k);
else
ins(rson, mid + 1, r, k);
sumt[p] = sumt[lson] + sumt[rson];
}
void del(int p, int l, int r, int k){
if (l == r) {
if (k <= sumt[p]) sumt[p]--;
return ;
}
int mid = l + r >> 1;
if (sumt[lson] >= k) del(lson, l, mid, k);
else del(rson, mid + 1, r, k - sumt[lson]);
sumt[p] = sumt[lson] + sumt[rson];
}
int flag = 0;
void query(int p, int l, int r){
if (l == r){
if (sumt[p]) { flag = l; }
return ;
}
int mid = l + r >> 1;
query(lson, l, mid);
query(rson, mid + 1, r);
}
int main(){
int n, q, x; RD(n, q);
for(int i = 1; i <= n; i++){
RD(x); ins(1, 1, n, x);
}
for(int que = 1; que <= q; que++){
RD(x);
if (x > 0) ins(1, 1, n, x);
else { del(1, 1, n, abs(x));}
}
query(1, 1, n);
if (sumt[1]!=0) cout << flag << '\n';
else cout << 0 << '\n';
}
//树状数组
const int maxn = 1e6+60;
int t[maxn];
struct Bit
{
void ins(int x, int v) {
for(; x < maxn; x += x&-x) t[x] += v;
}
int query(int x) {
LL res = 0;
for(; x; x -= x&-x) res += t[x];
return res;
}
void erase(int k) {
int now = 0;
for(int i = 19; i > 0; --i){
if (t[now|(1<<i)] < k){
k -= t[now | (1<<i)];
now |= 1 << i;
}
}
if (t[now|1] < k) ins(now+2, -1);
else ins(now+1, -1);
}
} bit;
int main(){
int n, q; RD(n, q);
FOR_1(i, 1, n){
int x; scanf("%d", &x); bit.ins(x, 1);
}
FOR_1(ca, 1, q){
int k; scanf("%d", &k);
if(k > 0) bit.ins(k, 1);
else{
bit.erase(-k);
}
}
if(!bit.query(n)){
cout << 0 << '\n';
}
else{
FOR_1(i, 1, n){
if(bit.query(i)){
cout << i << '\n';
return 0;
}
}
}
}