2022.10.23
2022.10.23
稍微写一哈。
现在好多人叫我学姐呀!
有点美滋滋的。虽然教不了他们什么了。可以考试帮大家垫垫底。
哦!这 8 天的缘分!
上午效率怪低的。
贪心贪不明白,搜索搜不明白。
/*
Date:2022.10.23
Source:LOJ
knowledge:贪心 按结束时间排序,每个区间的树都先区间的右侧种,以达到最大的重合
至于为什么按结束时间排序,手摸样例感性理解一下,大概是会有更多的重复的空间。
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#define orz cout << "AK IOI" << "\n";
using namespace std;
const int maxn = 3e4 + 10;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
int n, m, ans;
bool vis[maxn];
struct node{
int b, e, t;
}a[maxn];
bool cmp(node a, node b)
{
return a.e < b.e;
}
int main()
{
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
n = read(), m = read();
for(int i = 1; i <= m; i++)
a[i].b = read(), a[i].e = read(), a[i].t = read();
sort(a + 1, a + m + 1, cmp);
for(int i = 1; i <= m; i++)
{
int k = 0;
for(int j = a[i].b; j <= a[i].e; j++) if(vis[j]) k++;
if(k >= a[i].t) continue;
for(int j = a[i].e; j >= a[i].b; j--)
{
if(!vis[j]) vis[j] = 1, k++, ans++;
if(k >= a[i].t) break;
}
}
print(ans);
//fclose(stdin);
//fclose(stdout);
return 0;
}
/*
Date:2022.10.22
Source:LUOGU 4145
knowledge:永远猜不到出题人在想什么
注意开平方,sqrt(1) = 1, 最大的数开次平方就会到1,所以要记录区间最大值,若为1,则不用进行操作
进行单点修改
*/
#include <cstdio>
#include <cmath>
#include <iostream>
#define orz cout << "AK IOI" << "\n";
#define int long long
#define ls rt << 1
#define rs rt << 1 | 1
using namespace std;
const int maxn = 1e5 + 10;
const int maxm = 2e5 + 10;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
int n, m, a[maxn];
struct tree{
int sum, l, r, maxx;
}t[maxn << 2];
void push_up(int rt)
{
t[rt].sum = t[ls].sum + t[rs].sum;
t[rt].maxx = Max(t[ls].maxx, t[rs].maxx);
}
void build(int rt, int l, int r)
{
t[rt].l = l, t[rt].r = r;
if(l == r)
{
t[rt].sum = t[rt].maxx = a[l];
return ;
}
int mid = l + r >> 1;
build(ls, l, mid), build(rs, mid + 1, r);
push_up(rt);
}
int query(int rt, int l, int r)
{
if(t[rt].l >= l && t[rt].r <= r) return t[rt].sum;
int mid = (t[rt].l + t[rt].r) >> 1, ans = 0;
if(l <= mid) ans += query(ls, l, r);
if(r > mid) ans += query(rs, l, r);
return ans;
}
void updata(int rt, int l, int r)
{
if(t[rt].l == t[rt].r)
{
t[rt].maxx = sqrt(t[rt].maxx);
t[rt].sum = sqrt(t[rt].sum);
return ;
}
int mid = (t[rt].l + t[rt].r) >> 1;
if(l <= mid && t[ls].maxx > 1) updata(ls, l, r);
if(r > mid && t[rs].maxx > 1) updata(rs, l, r);
push_up(rt);
}
signed main()
{
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
n = read();
for(int i = 1; i <= n; i++) a[i] = read();
m = read();
build(1, 1, n);
for(int i = 1; i <= m; i++)
{
int x = read(), l = read(), r = read();
if(l > r) swap(l, r);
if(x == 1) printf("%lld\n", query(1, l, r));
else updata(1, l, r);
}
//fclose(stdin);
//fclose(stdout);
return 0;
}
关于考试……
代码能力严重下降,或者一直都没好过,30min 左右读题,然后 T4 暴力生写了一个小时,然后调的过程中发现自己写错了,然后又花了 30 min 写了 16 分的暴力。
然后 T3 30min, T4 30min, T1 不到 50 min,最后 10 min 整理了文件夹,然后开始喝茶。
总体感觉,能拿的无脑暴力分有了,还要拿经过思考后的分。
主要问题在于代码能力太菜了,留给自己思考的时间,发现规律的时间不多。虽然感觉也发现不了
T1
枚举 \(x\) 和 \(y\) 判断合法的 \(z\) 的位置,倒序枚举 \(y\), 用 \(map\) 记录\([y + 1, n]\) 区间内每个数出现的次数,每次答案加上 \(gcd(a_x, a_y)\) 的个数, \(y\) 减小的时候将 \(a_y\) 入桶。
感觉应该想到的。
/*
Date:2022.10.23
Source: 模拟赛补题
knowledge:
*/
#include <cstdio>
#include <iostream>
#include <map>
#define orz cout << "AK IOI" << "\n";
using namespace std;
const int maxn = 3010;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
int n, a[maxn];
long long ans;
map<int, int> mp;
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
int main()
{
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
n = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= n; i++)
{
mp.clear();
for(int j = n; j > i; --j)
{
ans += mp[gcd(a[i], a[j])];
mp[a[j]]++;
}
}
printf("%lld", ans);
//fclose(stdin);
//fclose(stdout);
return 0;
}
T2
拿了爆搜的 $30pts。
正解 \(DP\) + 二分。这个 \(dp\) 还是蛮简单的,就是很久没写了吧。找理由
这个题的分算是拿满了吧。
/*
Date:2022.10.24
Source:模拟赛补题
knowledge: 二分 + DP
很好,二分怎么写来着?
f[i]表示 以i结尾的符合条件的最长子序列的长度
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#define orz cout << "AK IOI" << "\n";
#define int long long
using namespace std;
const int maxn = 1010;
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') f = -1; ch = getchar();}
while(ch <= '9' && ch >= '0') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
inline void print(int X)
{
if(X < 0) X = ~(X - 1), putchar('-');
if(X > 9) print(X / 10);
putchar(X % 10 ^ '0');
return ;
}
inline int Max(int a, int b){
return a > b ? a : b;
}
inline int Min(int a, int b){
return a < b ? a : b;
}
inline int Abs(int a){
return a > 0 ? a : -a;
}
int n, m, a[maxn], l, r = -1, ans, f[maxn];
bool check(int k)
{
for(int i = 1; i <= n; i++) f[i] = 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j < i; j++)
if(Abs(a[i] - a[j]) <= k) f[i] = max(f[i], f[j] + 1);
for(int i = 1; i <= n; i++) if(f[i] >= m) return 1;
return 0;
}
signed main()
{
//freopen("cauchy7.in", "r", stdin);
//freopen(".out", "w", stdout);
n = read(), m = read();
for(int i = 1; i <= n; i++) a[i] = read(), r = Max(r, a[i]);
while(l <= r)
{
int mid = (l + r) >> 1;
if(check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
print(ans);
//fclose(stdin);
//fclose(stdout);
return 0;
}