2022.9.26———HZOI【CSP-S模拟12】游寄
好的今天是
得分
建议去看kiritokazuto的博
T1:开挂,T2:叁仟柒佰万,T3:超级加倍,T4:欢乐豆
场切题写丑了。气的我直接开贺
T1
/*
#include <iostream>
#include <algorithm>
#include <set>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout);
#define int unsigned long long
#define re register int
#define char_phi signed
#define DMARK cerr << "###"
#define _ ' '
#define Endl cout << '\n'
#define Dl cerr << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 1000005
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
struct node{int ai, bi;};
/*
这是个什么贪心捏。
显然地,应当是数列递增。
n 10^6我超
我知道了
但是不确定正确性
大胆猜规律
可以用bi交换。
我不大会弄,因为是基于值域的
看了一下似乎有68pts,如果这个贪心是对的话
再想一下特殊性质也许可以更高
大样例过了
但是最大的那个值域太大我算法整不了
所以现在写一下特殊性质A
哦哦然后忘记取模了(
等会,傻b吧,对2^64取模
这longlong开不下啊
我改成ull得了,啥玩意
性质A的分咋拿谔谔
不行,,也是基于值域的。。
我先开T2吧,有时间再回来
希望这个贪心别fake
*//*
unsigned long long final_ans;
int n, nn;
int dis[N];
multiset<int> hav[N];
multiset<int> s;
struct node a[N];
inline bool comp1(node A, node B){return ((A.ai == B.ai) ? (A.bi < B.bi) : (A.ai < B.ai));}
inline bool comp2(int A, int B){return A > B;}
inline void work(){
cin >> n;
for (re i = 1 ; i <= n ; ++ i)
cin >> a[i].ai;
for (re i = 1 ; i <= n ; ++ i){
cin >> a[i].bi;
}
int l, r;
sort(a+1, a+n+1, comp1); nn = n << 1;
for (re i = 1 ; i <= n ; ++ i)
hav[a[i].ai].insert(i);
/*for (re i = 1 ; i <= 10 ; ++ i)
cerr << hav[i].size() << _;
Dl;*//*
l = a[1].ai, r = a[1].ai;
for (; r <= nn ; ++ r){
if (hav[r].size() == 0){
while (hav[l].size() <= 1 and l < r)
l ++;
if (l == r)
continue;
dis[*hav[l].begin()] = r-l;
hav[l].erase(hav[l].begin());
}
}
/*for (re i = 1 ; i <= 10 ; ++ i)
cerr << hav[i].size() << _;
Dl;
cerr << "dis ";
for (re i = 1 ; i <= 10 ; ++ i)
cerr << dis[i] << _;
Dl;*//*
for (re i = 1 ; i <= n ; ++ i)
s.insert(a[i].bi);
/*for (re i = 1 ; i <= n ; ++ i){
if (dis[i] != 0)
final_ans = final_ans + (long long)dis[i] * (*s.begin());
}*//*
sort(dis+1, dis+n+1, comp2);
/*cerr << "dis ";
for (re i = 1 ; i <= 10 ; ++ i)
cerr << dis[i] << _;
Dl;
cerr << "s: ";
for (auto it = s.begin() ; it != s.end() ; ++ it)
cerr << *it << _;
Dl;*//*
for (re i = 1 ; i <= n ; ++ i){
if (dis[i] == 0)
break;
// cerr << final_ans << _ << dis[i] << _ << (*s.begin()) << _ << dis[i] * (*s.begin()) << '\n';
final_ans = final_ans + (unsigned long long)dis[i] * (*s.begin());
s.erase(s.begin());
}
cout << final_ans << '\n';
return ;
}
// #define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(a);
#endif
Fastio_setup();
work();
return GMY;
}
*/
#include <iostream>
#include <algorithm>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define re register int
#define char_phi signed
#define DMARK cerr << "###"
#define _ ' '
#define Endl cout << '\n'
#define Dl cerr << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 1000005
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
struct Stack{int l, r, len;};
/*
场切题写丑了
*/
int n, top;
unsigned long long final_ans;
int a[N], b[N], dis[N];
struct Stack s[N];
inline bool comp1(int A, int B){return A > B;}
inline void work(){
cin >> n;
for (re i = 1 ; i <= n ; ++ i)
cin >> a[i];
for (re i = 1 ; i <= n ; ++ i)
cin >> b[i];
sort(a+1, a+n+1); s[++ top] = (Stack){a[n], a[n], 1};
for (re i = n ; i >= 1 ; -- i){
if (a[i] == a[i+1])
dis[++ dis[0]] = s[top].len, s[top].r ++, s[top].len ++;
else
s[++ top] = (Stack){a[i], a[i], 1};
while (top > 1 and s[top].r == s[top-1].l - 1)
s[top-1].l = s[top].l, s[top-1].len += s[top].len, top --;
}
sort(b+1, b+n+1); sort(dis+1, dis+dis[0]+1, comp1);
for (re i = 1 ; i <= dis[0] ; ++ i)
final_ans = final_ans + (unsigned long long)b[i] * dis[i];
cout << final_ans << '\n';
}
// #define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(a);
#endif
Fastio_setup();
work();
return GMY;
}
题面说的那个 就是 整个序列的 。浅证一下。
设题面说的那个 为 ,总序列的 为 。
首先 肯定不会大于 。考虑 时是否成立。
假设你要选区间①的 作为答案 (也就是 ),那么 这个数显然不会在区间①内出现。但是由于区间总 不等于 ,所以 一定在其他区间内出现,这就意味着在总有一个区间他的 不能为 (可能比 小也可能比 大,但不会是 )。
然后就证毕了。
啊对对对,你证了这个了,然后呢?
我不会!开贺!
T2
#include <iostream>
#include <cstring>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define re register int
#define char_phi signed
#define DMARK cerr << "###"
#define _ ' '
#define Endl cout << '\n'
#define Dl cerr << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 37000005
#define P 1000000007
#define mod %
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
/*
“mex是整个序列的mex”
确实
“记一个单调指针就可以达到线性了。”
确实
然后嘞
我记f[i][0/1]在这个数不断开或断开一次,然后我咋转移嘞
*/
int T, n, mex;
int a[N], f[N], cnt[N];
inline void Clean(){memset(f, 0, sizeof(f)); memset(cnt, 0, sizeof(cnt));}
inline void work(){
Clean();
cin >> n;
if (n == 37000000){
a[1] = 0; cnt[0] = 1;
int x, y; cin >> x >> y;
for (re i = 2 ; i <= n ; ++ i)
{a[i] = (((long long)a[i-1]*x + y + i) & 262143); cnt[a[i]] ++;}
}
else {
for (re i = 1 ; i <= n ; ++ i)
{cin >> a[i]; cnt[a[i]] ++;}
}
mex = 0;
while (cnt[mex] != 0)
mex ++;
f[0] = 1; memset(cnt, 0, sizeof(cnt));
for (re i = 1, l(1), mxs(0) ; i <= n ; ++ i){
cnt[a[i]] ++;
while (cnt[mxs] != 0)
mxs ++;
f[i] = f[i-1];
if (mxs == mex){
while ((a[l] > mex or cnt[a[l]] > 1) and l < i)
cnt[a[l]] --, l ++;
f[i] = ((long long)f[i] + f[l-1]) mod P;
}
}
cout << (f[n]-f[n-1]+P) mod P << '\n';
/*Clean();
cin >> n;
for (re i = 1 ; i <= n ; ++ i)
cin >> a[i];
for (re i = 1, ans ; i <= n ; ++ i){
cnt[a[i]] ++; ans = 0;
for (re j = i ; j <= n ; ++ j){
cnt[a[j]] ++;
while (cnt[ans] != 0)
ans ++;
mxs[i][j] = ans;
}
for (re j = i ; j <= n ; ++ j)
cnt[a[j]] --;
cnt[a[i]] --;
}
mex = mxs[1][n];
/*for (re i = 1 ; i <= n ; ++ i)
for (re j = i ; j <= n ; ++ j)
cerr << "[" << i << ", " << j << "]: " << mxs[i][j] << '\n';*//*
f[0] = 1;
// cerr << mex << '\n';
for (re i = 1 ; i <= n ; ++ i){
for (re j = 1 ; j <= i ; ++ j){
if (mxs[j][i] == mex)
f[i] += f[j-1];
while (f[i] >= P)
f[i] = f[i] mod P;
}
}
cout << f[n] << '\n';*/
}
// #define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(a, a);
#endif
Fastio_setup();
cin >> T;
while (T --)
work();
return GMY;
}
这道题我一上来就想到了某倍增连边的题(因为莫名找不到题了所以就不挂链接了)
我滴任务,完成啦!!!!!!!!
然后直接拿着这个思路硬干了几个小时,然后发现伪了。
为啥伪捏。
两个点不一定是父子关系捏。
然后怀着能拿链部分分的希冀直接去跑链的大样例。直接一发 掉。
然后就心态爆炸直接起飞。
正解是,是啥笛卡尔树,我不会,所以我直接贺题解。
但是学到了一些本来就应该会的玩意。
就是你一颗树,某个节点的子树内 序是连续的,根据这玩意可以套树状数组之类的数据结构。
T3
#include <iostream>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define int long long
#define re register int
#define char_phi signed
#define DMARK cerr << "###"
#define _ ' '
#define Endl cout << '\n'
#define Dl cerr << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 2000005
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
/*
为什么kirito能把每道题都讲明白啊
dfn~dfn+(dfn-sz+1)子树内连续的dfn序
*/
int n, final_ans, dfscnt;
int dfn[N], sz[N], fa[N], C[N];
struct star{
int star_cnt;
int head[N], v[N<<1], nxt[N<<1];
inline void star_add(int uu, int vv){v[++ star_cnt]=vv, nxt[star_cnt]=head[uu], head[uu]=star_cnt;}
};
struct star e, up, dw;
int find(int x){return ((fa[x] == x) ? (x) : (fa[x] = find(fa[x])));}
inline void Unite(int x, int y){x = find(x), y = find(y); fa[y] = x;}
#define lowbit(x) ((x) & (-(x)))
inline void Update(int k, int w){
while (k <= n)
C[k] += w, k += lowbit(k);
}
inline int Query(int k){
int res(0);
while (k != 0)
res += C[k], k -= lowbit(k);// , cerr << k << '\n'
return res;
}
void dfs1(int x){
dfn[x] = ++ dfscnt; sz[x] = 1;
for (re i = dw.head[x] ; i ; i = dw.nxt[i]){
int v = dw.v[i];
dfs1(v);
sz[x] += sz[v];
}
}
void dfs2(int x){
final_ans += Query(dfn[x]+sz[x]-1) - Query(dfn[x]-1);
Update(dfn[x], 1);
for (re i = up.head[x] ; i ; i = up.nxt[i]){
int v = up.v[i];
dfs2(v);
}
Update(dfn[x], -1);
}
inline void work(){
cin >> n; cin >> dfscnt; dfscnt = 0;
for (re uu = 2, vv ; uu <= n ; ++ uu)
{cin >> vv; e.star_add(vv, uu), e.star_add(uu, vv);}
for (re i = 1 ; i <= n ; ++ i)
fa[i] = i;
for (re i = 1 ; i <= n ; ++ i)
for (re j = e.head[i] ; j ; j = e.nxt[j])
if (e.v[j] < i)
up.star_add(i, find(e.v[j])), Unite(i, e.v[j]);
for (re i = 1 ; i <= n ; ++ i)
fa[i] = i;
for (re i = n ; i >= 1 ; -- i)
for (re j = e.head[i] ; j ; j = e.nxt[j])
if (e.v[j] > i)
dw.star_add(i, find(e.v[j])), Unite(i, e.v[j]);
dfs1(1);
/*for (re i = 1 ; i <= n ; ++ i)
cerr << "dfn、sz: " << dfn[i] << _ << sz[i] << '\n';*/
dfs2(n);
cout << final_ans << '\n';
}
// #define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(a, a);
#endif
Fastio_setup();
work();
return GMY;
}
子任务分治可得 的好成绩
正解我还是不会,直接贺
T4
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define int long long
#define re register int
#define char_phi signed
#define DMARK cerr << "###"
#define _ ' '
#define Endl cout << '\n'
#define Dl cerr << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 100005
#define MPOS 3005
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL);}
struct star{int v, w;};
struct node{
int id, w;
char lt;
friend bool operator < (node A, node B){return A.w > B.w;}
};
/*
kirito讲得很好,但是
*/
int n, m, mn, aid, final_ans;
char vis[N];
int a[N], s[N], dis[N], fa[N], id[N];
vector<star> e[N];
priority_queue<node> q;
int find(int x){return ((fa[x] == x) ? (x) : (fa[x] = find(fa[x])));}
inline void Insert(int x, int w){
if (fa[x] != x)
return ;
dis[x] = w; fa[x] = x+1;
q.push((node){x, dis[x]+a[s[x]], true});
for (re i = 0 ; i < e[x].size() ; ++ i){
int v = e[x][i].v;
if (dis[v] > dis[x]+e[x][i].w)
{dis[v] = dis[x]+e[x][i].w; q.push((node){v, dis[v], false});}
}
}
inline void Dijskra(int rt){
memset(dis, 0x5f, sizeof(dis)); dis[rt] = 0;
fa[s[0]+1] = s[0]+1;
for (re i = 1 ; i <= s[0] ; ++ i)
fa[i] = i;
q.push((node){rt, dis[rt], false});
while (q.empty() == false){
node x = q.top(); q.pop();
if (x.lt == false)
Insert(x.id, x.w);
else {
for (re i = 0 ; i < e[x.id].size() ; ++ i)
vis[e[x.id][i].v] = true;
for (re i = find(1) ; i <= s[0] ; i = find(i+1))
if (vis[i] == false)
Insert(i, x.w);
for (re i = 0 ; i < e[x.id].size() ; ++ i)
vis[e[x.id][i].v] = false;
}
}
}
inline void work(){
cin >> n >> m;
for (re i = 1 ; i <= n ; ++ i)
cin >> a[i];
for (re i = 1, x, y, z ; i <= m ; ++ i){
cin >> x >> y >> z;
if (id[x] == 0)
{s[++ s[0]] = x; id[x] = s[0];}
if (id[y] == 0)
{s[++ s[0]] = y; id[y] = s[0];}
e[id[x]].push_back((star){id[y], z});
}
a[0] = 1145141919; mn = 1145141919;
for (re i = 1 ; i <= n ; ++ i)
if (id[i] == 0 and a[i] < mn)
mn = a[i], aid = i;
if (mn != 1145141919)
s[++ s[0]] = aid, id[aid] = aid;
for (re i = 1 ; i <= n ; ++ i)
if (id[i] == 0)
final_ans += (long long)a[i] * (n-1);
for (re i = 1 ; i <= s[0] ; ++ i){
Dijskra(i); mn = 1145141919;
for (re j = 1 ; j <= s[0] ; ++ j){
final_ans += dis[j];
mn = MIN(mn, dis[j]+a[s[j]]);
}
final_ans += (n-s[0])*mn;
}
cout << final_ans << '\n';
}
// #define IXINGMY
char_phi main(){
#ifdef IXINGMY
FBI_OPENTHEDOOR(a, a);
#endif
Fastio_setup();
work();
return GMY;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现