NOIP 模拟赛 2
NOIP 模拟赛总结
NOIP 模拟赛 2
诶嘿嘿,我是 rnk1 欸
T1 数字(math)
简单签到题,发现位数限制根本没用。(直接加小数点即可)
然后不断贪心地取值。
设第一个较大值给了 \(a\)。
剩余的较大值直接全给 \(b\)。
最后上个高精乘就成功地 A 掉了这道题。
点击查看代码
#include <bits/stdc++.h>
#define Blue_Archive return 0
#define int long long
using namespace std;
constexpr int N = 1e4 + 3;
constexpr int INF = 0x3f3f3f3f;
int T;
int a;
int b;
int len;
int aa[N];
int bb[N];
int ans[N];
int cnt[N];
inline void GaoJingCheng()
{
for(int i = 1;i <= a;i ++)
{
for(int j = 1;j <= b;j ++)
{
ans[i + j - 1] += aa[i] * bb[j];
}
}
for(int i = 1;;i ++)
{
if(ans[i] > 9)
{
ans[i + 1] += ans[i] / 10;
ans[i] %= 10;
}
if(ans[i + 1] == 0)
{
len = i;
break;
}
}
}
inline void work()
{
memset(aa,0,sizeof(aa));
memset(bb,0,sizeof(bb));
memset(ans,0,sizeof(ans));
memset(cnt,0,sizeof(cnt));
cin >> a >> b;
len = min(a,b);
if(a > b) swap(a,b);
bool op = 1; // 判断两个数是否有不同(钦定 a > b)
for(int i = 1;i <= 9;i ++) cin >> cnt[i];
for(int i = 9,now = 0,las = 0;i >= 1;i --)
{
if(!cnt[i]) continue;
if(las)
{
if(las == 1) bb[now] = i;
if(las == 2) aa[now] = i;
las = 0;
cnt[i] --;
}
if(cnt[i] >= (len - now) * 2 + (las != 0))
{
while(now != len)
{
aa[++ now] = i;
bb[now] = i;
cnt[i] -= 2;
}
break;
}
if(cnt[i] >= 2)
{
int tim = cnt[i] / 2;
while(tim)
{
aa[++ now] = i;
bb[now] = i;
tim --;
}
}
cnt[i] %= 2;
if(cnt[i] != 0)
{
if(op)
{
aa[++ now] = i;
las = 1;
op = 0;
}
else
{
bb[++ now] = i;
las = 2;
}
cnt[i] --;
}
}
for(int i = 9,now = len;i >= 1;i --)
{
if(!cnt[i]) continue;
while(cnt[i]) bb[++ now] = i,cnt[i] --;
}
for(int i = 1;i <= a / 2;i ++) swap(aa[i],aa[a - i + 1]);
for(int i = 1;i <= b / 2;i ++) swap(bb[i],bb[b - i + 1]);
len = 0;
GaoJingCheng();
for(int i = len;i;i --) cout << ans[i];
cout << '\n';
}
signed main()
{
freopen("math.in","r",stdin);freopen("math.out","w",stdout);
// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin >> T;
while(T --) work();
Blue_Archive;
}
T2 游戏(game)
发现是简单贪心,可以直接拆环扩成二倍的链。
设该点左右两端各 \({n / 2}\) 区间的和为 \(w\)。
答案即是 \(\max_{i = 1}^{n} min_{j = i}^{i + n - 1}w_j\)。
直接简单线段树维护。
点击查看代码
#include <bits/stdc++.h>
#define Blue_Archive return 0
#define lid (id << 1)
#define rid (id << 1 | 1)
using namespace std;
constexpr int N = 1e6 + 3;
constexpr int INF = 2e9;
int n;
int ans;
int a[N];
int b[N];
int sum[N];
int tr[N << 2];
inline void build(int id,int l,int r)
{
if(l == r) return void(tr[id] = b[l]);
int mid = (l + r) >> 1;
build(lid,l,mid);
build(rid,mid + 1,r);
tr[id] = min(tr[lid],tr[rid]);
}
inline int query(int id,int l,int r,int L,int R)
{
if(L > R || L > r || l > R) return INF;
if(L <= l && r <= R) return tr[id];
int mid = (l + r) >> 1;
return min(query(lid,l,mid,L,R),query(rid,mid + 1,r,L,R));
}
signed main()
{
freopen("game.in","r",stdin);freopen("game.out","w",stdout);
// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin >> n;
int len = (n + 1) / 2;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
a[i + n] = a[i];
}
for(int i = 1;i <= (n << 1);i ++) sum[i] = sum[i - 1] + a[i];
for(int i = 1;i + len - 1 <= n * 2;i ++) b[i] = sum[i + len - 1] - sum[i - 1];
for(int i = n * 2 - len + 2;i <= 2 * n;i ++) b[i] = INF;
build(1,1,n << 1);
ans = 0;
for(int i = len,res;i <= 2 * n - len + 1;i ++)
{
res = query(1,1,n << 1,i - len + 1,i);
ans = max(ans,res == INF ? 0 : res);
}
cout << ans << '\n';
Blue_Archive;
}
T3:海报(posters)
卡时救了我qwq。
爆搜 + 剪枝。
发现如果有两个或更多个放在对角线(或角落里)肯定不劣。
剩下的直接爆搜即可。
注意剪枝:如果这个点已经被覆盖了,那么直接跳过,跑得飞快qwq。
点击查看代码
#include <bits/stdc++.h>
#define Blue_Archive return 0
#define int long long
#define lid (id << 1)
#define rid (id << 1 | 1)
using namespace std;
constexpr int N = 1e2 + 3;
constexpr int INF = 2e9;
int n;
int m;
int K;
int ans;
bool vis[N][N];
pair<int,int> pos[8];
struct miku
{
int l,r;
}op[N];
inline void check()
{
int res = 0;
for(int k = 1,upl,upr;k <= K;k ++)
{
if(op[k].l + pos[k].first - 1 < n) upl = op[k].l + pos[k].first - 1;
else upl = n;
if(op[k].r + pos[k].second - 1 < m) upr = op[k].r + pos[k].second - 1;
else upr = m;
for(int i = pos[k].first;i <= upl;i ++)
{
for(int j = pos[k].second;j <= upr;j ++)
{
vis[i][j] = 1;
}
}
}
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= m;j ++)
{
if(vis[i][j])
{
res ++;
vis[i][j] = 0;
}
}
}
ans = max(ans,res);
if(clock() > 950000)
{
cout << ans << '\n';
exit(0);
}
}
inline void dfs(int x,int res)
{
if(x + K - res > 6) return;
if(x == 6)
{
if(res != K) return;
check();
return;
}
dfs(x + 1,res);
for(int i = 1;i <= K;i ++)
{
if(pos[i].first && pos[i].second) continue;
if(x == 1) pos[i] = {1,1},dfs(x + 1,res + 1),pos[i] = {0,0};
if(x == 2) pos[i] = {1,m - op[i].r + 1},dfs(x + 1,res + 1),pos[i] = {0,0};
if(x == 3) pos[i] = {n - op[i].l + 1,1},dfs(x + 1,res + 1),pos[i] = {0,0};
if(x == 4) pos[i] = {n - op[i].l + 1,m - op[i].r + 1},dfs(x + 1,res + 1),pos[i] = {0,0};
if(x == 5)
{
for(int j = 1;j + op[i].l <= n;j ++)
{
for(int k = 1;k + op[i].r <= m;k ++)
{
pos[i] = {j,k};
dfs(x + 1,res + 1);
pos[i] = {0,0};
}
}
}
}
}
signed main()
{
freopen("posters.in","r",stdin);freopen("posters.out","w",stdout);
// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin >> n >> m >> K;
for(int i = 1;i <= K;i ++) cin >> op[i].l;
for(int i = 1;i <= K;i ++) cin >> op[i].r;
if(K == 1)
{
ans = min(n,op[1].l) * min(m,op[1].r);
cout << ans << '\n';
exit(0);
}
if(K == 2)
{
int upl,upr;
upl = min(op[1].l,n);
upr = min(op[1].r,m);
for(int i = 1;i <= upl;i ++)
{
for(int j = 1;j <= upr;j ++)
{
vis[i][j] = 1;
}
}
upl = max(n - op[2].l + 1,1ll);
upr = max(m - op[2].r + 1,1ll);
for(int i = upl;i <= n;i ++)
{
for(int j = upr;j <= m;j ++)
{
vis[i][j] = 1;
}
}
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= m;j ++)
{
if(vis[i][j]) ans ++;
}
}
cout << ans << '\n';
exit(0);
}
if(K >= 3)
{
dfs(0,0);
cout << ans << '\n';
exit(0);
}
Blue_Archive;
}
T4:环(ring)
根号分治,可惜场上没时间写完了。
直接对环的大小进行根号分治即可。
点击查看代码
#include <bits/stdc++.h>
#define Blue_Archive return 0
#define int long long
using namespace std;
constexpr int N = 1.5e5 + 3;
constexpr int M = 400;
constexpr int INF = 2e9;
int n;
int m;
int q;
int len;
int top;
int a[N];
int c[N];
int id[N];
int st[M];
int ed[M];
int laz[N];
int sum[N];
int siz[N];
int stk[N];
int sum2[N];
vector<int> f[N],sum1[N];
inline void update(int x)
{
if(siz[x] > len) return void(laz[x] ++);
for(int i = f[x].size() - 1;i >= 1;i--)
{
sum[id[f[x][i]]] = sum[id[f[x][i]]] - a[f[x][i]] + a[f[x][i - 1]];
sum[id[f[x][i - 1]]] = sum[id[f[x][i - 1]]] + a[f[x][i]] - a[f[x][i - 1]];
swap(a[f[x][i]],a[f[x][i - 1]]);
}
}
inline int query(int l,int r)
{
int res = 0;
if(id[l] == id[r])
{
for(int i = l;i <= r;i ++)
{
if(siz[c[i]] > len) continue;
res += a[i];
}
}
else
{
for(int i = l;i <= ed[id[l]];i ++)
{
if(siz[c[i]] > len) continue;
res += a[i];
}
for(int i = st[id[r]];i <= r;i ++)
{
if(siz[c[i]] > len) continue;
res += a[i];
}
for(int i = id[l] + 1;i < id[r];i ++) res += sum[i];
}
for(int i = 1,ql,qr,ansl,ansr;i <= top;i ++)
{
ql = lower_bound(f[stk[i]].begin(),f[stk[i]].end(),l) - f[stk[i]].begin();
qr = upper_bound(f[stk[i]].begin(),f[stk[i]].end(),r) - f[stk[i]].begin() - 1;
if(ql > qr) continue;
ansl = ((ql - laz[stk[i]]) % siz[stk[i]] + siz[stk[i]]) % siz[stk[i]];
ansr = ((qr - laz[stk[i]]) % siz[stk[i]] + siz[stk[i]]) % siz[stk[i]];
if(ansl <= ansr)
{
if(ansl == 0) res += sum1[stk[i]][ansr];
else res += sum1[stk[i]][ansr] - sum1[stk[i]][ansl - 1];
}
else res += sum1[stk[i]][ansr] + sum1[stk[i]][siz[stk[i]] - 1] - sum1[stk[i]][ansl - 1];
}
return res;
}
signed main()
{
freopen("ring.in","r",stdin);freopen("ring.out","w",stdout);
// freopen("data.in","r",stdin);freopen("data.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin >> n >> m >> q;
len = sqrt(n);
for(int i = 1;i <= n;i ++) cin >> c[i],siz[c[i]] ++;
for(int i = 1;i <= m;i ++) f[i].reserve(siz[i] + 1),sum1[i].reserve(siz[i] + 1);
for(int i = 1;i <= n;i ++) f[c[i]].emplace_back(i);
for(int i = 1;i <= n;i ++)
{
id[i] = (i - 1) / len + 1;
cin >> a[i];
if(siz[c[i]] <= len) sum[id[i]] += a[i];
if(!st[id[i]]) st[id[i]] = i;
ed[id[i]] = i;
}
for(int i = 1;i <= m;i ++)
{
if(siz[i] <= len) continue;
stk[++ top] = i;
for(int j = 1;j <= siz[i];j ++)
{
sum2[j] = sum2[j - 1] + a[f[i][j - 1]];
sum1[i].emplace_back(sum2[j]);
}
}
for(int i = 1,op,l,r,x;i <= q;i ++)
{
cin >> op;
if(op == 1)
{
cin >> l >> r;
cout << query(l,r) << '\n';
}
else
{
cin >> x;
update(x);
}
}
Blue_Archive;
}
与你的日常,便是奇迹

浙公网安备 33010602011771号