8.26 校内模拟赛 题解报告
作者:互联网
8.26 校内模拟赛 题解报告
扯
T1 优先队列没想到 到最后还以为是个结论题 拿着一个假结论交了
T2 排序 + 01 背包 很明显 BS 不会 01 背包
T3 不知道什么题 好像是个神仙搜索题 基本没看
大概这场考试就是这样...
这次是真的不想写.. 真的一个题都不会
本身考试的时候心态就很崩 T1 调了两个半小时还多 最后还是没调出来 也不知道怎么过的九十分 明明自己造的数据基本跑不过去的说
这场考试应该是考了几场试以来最烦躁的一场
题解同样不想写 也没法写什么 到现在 T2 依旧给不出合理的解释 在网上翻了很多题解 感觉给出的解释都比较笼统 最后还是不理解...
但是还是要写
到现在 T2 已经研究了一下午快一晚上了
到最后的时候 T3 想到一个比较暴力的写法 但是 T1 和 T2 都在崩的边缘 T3 又开的太晚了 于是就比较崩了 T3 最后也没写...
考的时候把 BS 的心态玩崩的是 T1
考完以后把 BS 的心态玩崩的是 T2
至于 T3 感觉太毒瘤了 反而基本没看 主要还是没搜到题解
得分情况
90 + 0 + 0 = 90
T1 得分比预期高 其实 BS 以为有分就不错了 完全没想到能过 90 毕竟 BS 现在这里(或者说考试的时候)就有五六组的数据可以将这个做法卡掉
T2 没看到空间限制 默认 256 之类的了 结果是 128 于是就爆零了
T3 没写 心态炸裂
题解
比起上一场的题解近乎什么都没讲 这一场的直接没有题解 逐渐敷衍
除了 T1 比较简单但是 BS 依旧挂掉以外 其他两个题都没有弄完 但是还是要写题解报告
T1 吃鱼 (fish)
BS 的错误结论就不放了 大家只要知道那个结论是错的就好了
用优先队列维护猫吃鱼的时间 枚举鱼 分给吃完的猫 最后把时间之内的弹出统计个数即可 具体见代码
代码
/*
Source: 吃鱼 (fish)
*/
#include<queue>
#include<cstdio>
#include<cstring>
#define pt putchar(' ')
#define pn putchar('\n')
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
/*----------------------------------------------------------*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*----------------------------------------------------------*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------------------------*/
int n, m, t, a[B], ans1, ans2;
struct node {
int t, x, id;
bool operator < (const node &a) const {return t == a.t ? x > a.x : t > a.t;}
};
std::priority_queue <node> q;
/*----------------------------------------------------------*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void Print(int x) {if(x < 0) putchar('-'), x = -x; if(x > 9) Print(x / 10); putchar(x % 10 ^ 48);}
/*----------------------------------------------------------*/
void Main() {
m = read(); n = read(); t = read(); m -= n; ans1 = m;
for(int i = 1; i ^ n + 1; i++) a[i] = read(), q.push((node){a[i], a[i], i});
for(int i = 1; i ^ m + 1; i++)
{
node x = q.top();
if(x.t == t) q.pop();
else if(x.t < t) q.pop(), x.t += x.x, q.push(x), ans1--;
}
while(!q.empty() && q.top().t <= t) q.pop(); ans2 = q.size();
Print(ans1); pt; Print(ans2); pn;
}
/*----------------------------------------------------------*/
signed main() {Main(); return 0;}
T2 01 背包威力加强版 (bag)
想留坑的 但是还是写了
要过的话很简单 按照 \(q - p\) 从小到大拍一下序 再跑一个 01 背包就可以了 甚至都不需要改什么东西
代码大概长这样
bool cmp(node x, node y) {return x.q - x.p < y.q - y.p;}
void Main() {
n = read(); m = read();
for(int i = 1; i ^ n + 1; i++) a[i] = (node){read(), read(), read()};
std::sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i ^ n + 1; i++) for(int j = m; j >= Max(a[i].p, a[i].q); j--)
f[j] = Max(f[j], f[j - a[i].p] + a[i].v)
Print(f[m]);
}
Q: 为什么要从小到大排序呢
A: 不知道
其实一开始看到的网上第一篇博客是从大到小排序的 但是 BS 写的时候没注意 写了从小到大的过了 又返回去看 试图理解的时候才发现
大概看了一下午 从大到小排或者从小到大排都能过(废话) 只是有些细节问题不一样就是了 具体来说的话就是跑 01 背包的时候 第二层循环的枚举范围不同
BS 大概能弄出来从大到小的那种排序方法 但是并不知道两种排序方法为什么会对应不一样的枚举范围
也去网上问了一下 只得到了消除后效性的答案 但是不理解具体是怎样
一下仅说个人理解
回到正题
先说从大到小的那种
考虑一般的贪心策略进行排序 这里只考虑选取的物品 并假定 \(p \leq q\)
对于第 \(i\) 个物品 购买所需要的最少的代价为 \(\sum_{j = 1}^{i - 1}p_j + q_i\) 设 \(sum_i = \sum_{j = 1}^i p_j\)
容易发现 前 \(i - 1\) 个物品的排列顺序不影响第 \(i\) 个物品的代价
考虑第 \(i\) 个物品与第 \(j\) 个物品的排列顺序
若 \(i\) 先于 \(j\)
则选取 \(i\) 与 \(j\) 的代价为
\[\max(sum_{i - 1} + q_i, sum_i + q_j) = \max(sum_{i - 1} + q_i, sum_{i - 1} + p_i + q_j) \]若 \(j\) 先于 \(i\)
则选取 \(i\) 与 \(j\) 的代价为
\[\max(sum_{j - 1} + q_j, sum_j + q_i) = \max(sum_{j - 1} + q_j, sum_{j - 1} + p_j + q_i) \]将相同项消除
显然前面一项不对答案做出影响
即考虑
\[\min(p_i + q_j, p_j + q_i) \]则当 \(i\) 先于 \(j\) 时 有
\[p_i + q_j < p_j + q_i\\ q_i - p_i > q_j - p_j \]也不知道对不对 反正 BS 是这样理解的
对应这种排序方式 在进行背包的时候第二维的枚举范围为 \([p, m - (q - p)]\)
考虑 \(dp\) 的状态 \(f_{i, j}\) 表示考虑前 \(i\) 个物品 占用背包容积 \(j\) 时的最大价值
在将要放入物品 \(i\) 时 需要保证剩余背包容积大于 \(q\) 即
\[m - j + p \geq q \]得到 \(j\) 的上界
\[j \leq m - (q - p) \]对于容量的下界即为 \(p\) 这里 BS 理解的是将物品限制在了上一层 这一层的下界就可以取到 \(p\)
此时由于 \(m\) 的位置不一定会转移到 所以不能作为最终答案 需要取最大值
对于按照 \(q - p\) 从小到大排序
枚举范围为 \([\max(p, q), m]\)
个人理解为将物品 \(i\) 归入本层
两种代码差不多
/*
Source: 01 背包威力加强版 (bag)
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define pt putchar(' ')
#define pn putchar('\n')
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
/*----------------------------------------------------------*/
const int A = 5e3 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*----------------------------------------------------------*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------------------------*/
int n, m, f[A];
struct node {int p, q, v;} a[A];
/*----------------------------------------------------------*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void Print(int x) {if(x < 0) putchar('-'), x = -x; if(x > 9) Print(x / 10); putchar(x % 10 ^ 48);}
/*----------------------------------------------------------*/
bool cmp(node x, node y) {return x.q - x.p < y.q - y.p;}
void Main() {
n = read(); m = read();
for(int i = 1; i ^ n + 1; i++) a[i] = (node){read(), read(), read()};
std::sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i ^ n + 1; i++) for(int j = m; j >= Max(a[i].p, a[i].q); j--)
f[j] = Max(f[j], f[j - a[i].p] + a[i].v);
Print(f[m]);
}
/*----------------------------------------------------------*/
signed main() {Main(); return 0;}
/*
Source: 01 背包威力加强版 (bag)
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define pt putchar(' ')
#define pn putchar('\n')
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
/*----------------------------------------------------------*/
const int A = 5e3 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*----------------------------------------------------------*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------------------------*/
int n, m, f[A], ans;
struct node {int p, q, v;} a[A];
/*----------------------------------------------------------*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void Print(int x) {if(x < 0) putchar('-'), x = -x; if(x > 9) Print(x / 10); putchar(x % 10 ^ 48);}
/*----------------------------------------------------------*/
bool cmp(node x, node y) {return x.q - x.p > y.q - y.p;}
void Main() {
n = read(); m = read();
for(int i = 1; i ^ n + 1; i++) a[i] = (node){read(), read(), read()};
std::sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i ^ n + 1; i++) for(int j = Min(m, m - (a[i].q - a[i].p)); j >= a[i].p; j--)
f[j] = Max(f[j], f[j - a[i].p] + a[i].v);
for(int i = 0; i <= m; i++) ans = Max(ans, f[i]);
Print(ans);
}
/*----------------------------------------------------------*/
signed main() {Main(); return 0;}
T3 崩 (beng)
感觉好像需要离散化加上什么神奇的搜索之类的(其实不清楚) 所以就跑路了
这里只丢一个七十的暴力
直接强行将经过的位置标记出来 然后从外面扫 最后搜不到的地方的个数就是答案
代码
/*
Source:
*/
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define pt putchar(' ')
#define pn putchar('\n')
#define pr std::pair <int, int>
#define mk std::make_pair
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define Max(x, y) ((x) > (y) ? (x) : (y))
#define Min(x, y) ((x) < (y) ? (x) : (y))
#define Swap(x, y) ((x) ^= (y) ^= (x) ^= (y))
/*----------------------------------------------------------*/
const int A = 3e3 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*----------------------------------------------------------*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------------------------*/
int n, a[A][A], ans;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, 1, -1};
bool vis[A][A];
std::queue <pr> q;
char s[3];
/*----------------------------------------------------------*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void Print(int x) {if(x < 0) putchar('-'), x = -x; if(x > 9) Print(x / 10); putchar(x % 10 ^ 48);}
/*----------------------------------------------------------*/
int Get(char c) {if(c == 'L') return 0; if(c == 'R') return 1; if(c == 'U') return 2; if(c == 'D') return 3;}
void bfs() {
vis[1][1] = 1; q.push(mk(1, 1));
while(!q.empty())
{
int x = q.front().first, y = q.front().second; q.pop();
for(int i = 0; i ^ 4; i++)
{
int xx = x + dx[i], yy = y + dy[i];
if(xx < 1 || xx > 3000 || yy < 1 || yy > 3000 || vis[xx][yy] || a[xx][yy]) continue;
vis[xx][yy] = 1; q.push(mk(xx, yy));
}
}
}
void Main() {
n = read(); int x = 1500, y = 1500;
for(int i = 1; i ^ n + 1; i++)
{
scanf("%s", s + 1); int k = read();
if(s[1] == 'L') a[x + dx[0] * k][y]++, a[x + 1][y + 1]++, a[x + dx[0] * k][y + 1]--, a[x + 1][y]--;
if(s[1] == 'R') a[x][y]++, a[x + dx[1] * k + 1][y + 1]++, a[x][y + 1]--, a[x + dx[1] * k + 1][y]--;
if(s[1] == 'U') a[x][y]++, a[x + 1][y + dy[2] * k + 1]++, a[x + 1][y]--, a[x][y + dy[2] * k + 1]--;
if(s[1] == 'D') a[x][y + dy[3] * k]++, a[x + 1][y + 1]++, a[x + 1][y + dy[3] * k]--, a[x][y + 1]--;
x += dx[Get(s[1])] * k; y += dy[Get(s[1])] * k;
}
for(int i = 1; i ^ 3001; i++) for(int j = 1; j ^ 3001; j++) a[i][j] += a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
bfs();
for(int i = 1; i ^ 3001; i++) for(int j = 1; j ^ 3001; j++) ans += !vis[i][j];
Print(ans);
}
/*----------------------------------------------------------*/
signed main() {Main(); return 0;}
然后贴一下标程
#include<bits/stdc++.h>
using namespace std;
#define li long long
#define gc getchar()
#define pc putchar
inline li read(){
li x = 0,y = 0,c = gc;
while(!isdigit(c)) y = c,c = gc;
while(isdigit(c)) x = (x << 1) + (x << 3) + (c ^ '0'),c = gc;
return y == '-' ? -x : x;
}
void print(li q){
if(q < 0){
pc('-');
q = -q;
}
if(q >= 10) print(q / 10);
pc(q % 10 + '0');
}
li s1 = 19260817,s2 = 23333333,s3 = 998244853,srd;
li rd(){
return srd = (srd * s1 + s2 + rand()) % s3;
}
//const int mo = 998244353;
//const int mo = 1000000007;
int n;
int a[1010],b[1010];
li ans;
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
//l:0 u:1 r:2 d:3
int nw[1010],mn[1010];
struct node{
int l,r,p;
}p1[1010],p2[1010],q1[1010],q2[1010];
int tot1,tot2,t1,t2;
inline bool operator < (node q,node w){
return q.p < w.p;
}
#define inf 2000000000
int bj[4010][4010];
int q[17000010][2];
int h,t;
void bf1(){
int i,j,nx,ny,tx,ty;
for(i = 1;i <= t1;++i){
for(j = q1[i].l;j <= q1[i].r;++j) bj[j + 1005][q1[i].p + 1005] = 1;
}
for(i = 1;i <= t2;++i){
for(j = q2[i].l;j <= q2[i].r;++j) bj[q2[i].p + 1005][j + 1005] = 1;
}
q[++t][0] = 1;q[t][1] = 1;bj[1][1] = 2;
while(h < t){
nx = q[++h][0];ny = q[h][1];
for(int i = 0;i < 4;++i){
tx = nx + dx[i];ty = ny + dy[i];
if(tx >= 1 && tx <= 2008 && ty >= 1 && ty <= 2008 && !bj[tx][ty]){
bj[tx][ty] = 2;
q[++t][0] = tx;q[t][1] = ty;
}
}
}
for(i = 1;i <= 2008;++i) for(j = 1;j <= 2008;++j) if(bj[i][j] != 2) ++ans;
print(ans);pc('\n');
}
struct lsh{
int x,id;bool fg,wz;
}ll[10010];
inline bool operator < (lsh q,lsh w){
return q.x < w.x;
}
int tot,len1[10010],len2[10010],nw1 = 1,nw2 = 1;
void work(){
int i,j,nx,ny,tx,ty;
++nw1;++nw2;h = t = ans = 0;memset(bj,0,sizeof(bj));
for(i = 1;i <= t1;++i){
for(j = q1[i].l;j <= q1[i].r;++j) bj[j][q1[i].p] = 1;
}
for(i = 1;i <= t2;++i){
for(j = q2[i].l;j <= q2[i].r;++j) bj[q2[i].p][j] = 1;
}
q[++t][0] = 1;q[t][1] = 1;bj[1][1] = 2;
while(h < t){
nx = q[++h][0];ny = q[h][1];
for(int i = 0;i < 4;++i){
tx = nx + dx[i];ty = ny + dy[i];
if(tx >= 1 && tx <= nw1 && ty >= 1 && ty <= nw2 && !bj[tx][ty]){
bj[tx][ty] = 2;
q[++t][0] = tx;q[t][1] = ty;
}
}
}
for(i = 1;i <= nw1;++i) for(j = 1;j <= nw2;++j) if(bj[i][j] != 2) ans += 1ll * len1[i] * len2[j];
print(ans);pc('\n');
}
int main(){
srand(time(0));rd();
register int i,j;
char c;
n = read();
int nwx = 0,nwy = 0,newx,newy;
for(i = 1;i <= n;++i){
c = gc;while(c < 'A' || c > 'Z') c = gc;
if(c == 'L') a[i] = 0;
else if(c == 'U') a[i] = 1;
else if(c == 'R') a[i] = 2;
else a[i] = 3;
b[i] = read();
newx = nwx + dx[a[i]] * b[i];newy = nwy + dy[a[i]] * b[i];
if(nwx == newx){
p2[++tot2].l = min(newy,nwy);
p2[tot2].r = max(newy,nwy);
p2[tot2].p = newx;
}
else{
p1[++tot1].l = min(newx,nwx);
p1[tot1].r = max(newx,nwx);
p1[tot1].p = newy;
}
nwx = newx;nwy = newy;
}
sort(p1 + 1,p1 + tot1 + 1);sort(p2 + 1,p2 + tot2 + 1);
q1[0].p = q2[0].p = -inf;
for(i = 1;i <= tot1;++i){
if(q1[t1].p == p1[i].p){
q1[t1].l = min(q1[t1].l,p1[i].l);
q1[t1].r = max(q1[t1].r,p1[i].r);
}
else q1[++t1] = p1[i];
}
for(i = 1;i <= tot2;++i){
if(q2[t2].p == p2[i].p){
q2[t2].l = min(q2[t2].l,p2[i].l);
q2[t2].r = max(q2[t2].r,p2[i].r);
}
else q2[++t2] = p2[i];
}
if(!t1){
print(q2[1].r - q2[1].l + 1);
return 0;
}
if(!t2){
print(q1[1].r - q1[1].l + 1);
return 0;
}
bool fg = 1;
for(i = 1;i <= t1;++i) if(q1[i].l < -1000 || q1[i].r > 1000 || q1[i].p < -1000 || q1[i].p > 1000) fg = 0;
for(i = 1;i <= t2;++i) if(q2[i].l < -1000 || q2[i].r > 1000 || q2[i].p < -1000 || q2[i].p > 1000) fg = 0;
if(fg){
bf1();
return 0;
}
for(i = 1;i <= t1;++i){
ll[++tot].x = q1[i].l;ll[tot].id = i;ll[tot].wz = 0;ll[tot].fg = 0;
ll[++tot].x = q1[i].r;ll[tot].id = i;ll[tot].wz = 1;ll[tot].fg = 0;
}
for(i = 1;i <= t2;++i){
ll[++tot].x = q2[i].p;ll[tot].id = i;ll[tot].wz = 0;ll[tot].fg = 1;
}
sort(ll + 1,ll + tot + 1);
for(i = 1;i <= tot;++i){
if(i == 1){
++nw1;
len1[nw1] = 1;
}
else if(ll[i].x - ll[i - 1].x == 1){
++nw1;
len1[nw1] = 1;
}
else if(ll[i].x - ll[i - 1].x > 1){
++nw1;len1[nw1] = ll[i].x - ll[i - 1].x - 1;
++nw1;len1[nw1] = 1;
}
if(ll[i].fg) q2[ll[i].id].p = nw1;
else if(ll[i].wz) q1[ll[i].id].r = nw1;
else q1[ll[i].id].l = nw1;
}
tot = 0;
for(i = 1;i <= t2;++i){
ll[++tot].x = q2[i].l;ll[tot].id = i;ll[tot].wz = 0;ll[tot].fg = 0;
ll[++tot].x = q2[i].r;ll[tot].id = i;ll[tot].wz = 1;ll[tot].fg = 0;
}
for(i = 1;i <= t1;++i){
ll[++tot].x = q1[i].p;ll[tot].id = i;ll[tot].wz = 0;ll[tot].fg = 1;
}
sort(ll + 1,ll + tot + 1);
for(i = 1;i <= tot;++i){
if(i == 1){
++nw2;
len2[nw2] = 1;
}
else if(ll[i].x - ll[i - 1].x == 1){
++nw2;
len2[nw2] = 1;
}
else if(ll[i].x - ll[i - 1].x > 1){
++nw2;len2[nw2] = ll[i].x - ll[i - 1].x - 1;
++nw2;len2[nw2] = 1;
}
if(ll[i].fg) q1[ll[i].id].p = nw2;
else if(ll[i].wz) q2[ll[i].id].r = nw2;
else q2[ll[i].id].l = nw2;
}
work();
return 0;
}
标签:ch,const,int,题解,++,8.26,read,校内,define 来源: https://www.cnblogs.com/blank-space-/p/15191680.html