7.28-8.11 中山集训
主要放模拟赛,还有一些简短的记录。
7.29
T2神秘 开幕雷击,不会。
T1
很简单直接模拟就行了,比CSP-S2023 T3简单多了。
喜报,没删调试语句,宝玲了。还有复杂度都可能会被卡,完全有更优的做法,做这种没脑子的题的时候还是要有脑子地去想想。
你说得对,但是删了调试就是对的,AC了😓😓😓
T2
一点背包都没想到,还以为是神秘 Ad-hoc,结果还是很简单。
直接考虑设 表示前 回合结束后剩下 个人, 的电量, 的石油时能获得的最大产品数,直接正常 01 背包转移就行了,注意转移不要越界,并且要时刻保证所有量非负。
但是发现 最大达到 级别,乘上 的话时间空间复杂度都不是很优,一个显然的trick是将 和 对调,也就是将状态设为 表示前 回合结束后剩下 个人, 的石油, 的产品时能获得的最大电量,最后统计答案时看这个方案的电量是否合法,然后对 取最大值就行了,这样子复杂度就降下来了。注意还是有一点卡常,所以注意背包转移中的上界不要全都是最大的,因为 单次变化量 。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll int
const ll N=114514,M=1919810;
ll n,m,hs,subid,dp[45][15][405][405];
//前 i 回合并且第 i 回合工作做完,剩 h 个人,g 单位石油,e 单位产品时的最大电量
struct xx{
ll h,g,p,e;
}a[N];
int main(){
freopen("grid.in","r",stdin);
freopen("grid.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m>>hs>>subid;
for(int i=1;i<=n;++i) cin>>a[i].h>>a[i].p>>a[i].g>>a[i].e;
memset(dp,-0x3f,sizeof(dp));
for(int i=1;i<=n;++i)
if(a[i].g>=0&&a[i].p>=0&&a[i].e>=0&&hs+a[i].h>=0)
dp[1][hs+a[i].h][a[i].g][a[i].e]=max(dp[1][hs+a[i].h][a[i].g][a[i].e],a[i].p);
for(int i=2;i<=m;++i)
for(int j=1;j<=n;++j)
for(int h=0;h<=hs;++h)
for(int g=0;g<=i*10;++g)
for(int e=0;e<=i*10;++e)
if(h>=a[j].h&&h-a[j].h<=hs&&
g>=a[j].g&&g-a[j].g<=400&&
e>=a[j].e&&e-a[j].e<=400&&
dp[i-1][h-a[j].h][g-a[j].g][e-a[j].e]+a[j].p>=0)
dp[i][h][g][e]=max(dp[i][h][g][e],dp[i-1][h-a[j].h][g-a[j].g][e-a[j].e]+a[j].p);
ll ans=0;
for(int i=1;i<=m;++i)
for(int h=0;h<=hs;++h)
for(int g=0;g<=400;++g)
for(int e=0;e<=400;++e)
if(dp[i][h][g][e]>=0) ans=max(ans,e);//,cout<<i<<" "<<h<<" "<<g<<" "<<e<<" "<<dp[i][h][g][e]<<'\n';
cout<<ans;
return 0;
}/*5 40 8 0
-1 400 0 0
-2 -1200 5 0
-1 -1200 10 -10
0 2000 -2 0
0 -240 -1 5
拥有蒟蒻的力量,退役是必然的*/
T3
真的,非常,他妈的,简单,那个方程,我他妈,甚至还做过,真的,服了,我个傻逼。
题中给的方程就是裴蜀定理的形式:问 有多少个不超过 的正整数解。根据裴蜀定理,或者自己推一推就能发现,能拼出来的数都是这段数 的倍数,答案就是 ,修改的话用线段树轻松维护,没了。
我他妈为啥没做出来?因为我傻到以为 不能是负数,要是带进去一推就知道是 了,啊啊啊啊啊啊啊啊啊啊
T4
还算简单,待补。
最后咱发现不犯低级错误可以140,稍微长点脑子可以240,有点想法可以340,这说明我就是个🤡
不过今天发现了一些以前关注的人也来这里了,不知道他们是啥学校的。
7.30
啊啊啊一整天都在听课,打题时间少死了,明天来补。
学了学过的 dp 和一些图论,图论部分还是有收获的。
晚上被dp题硬控。
7.31
啊啊啊比前天还寄,难度高了一些然后就全都不会做了,为啥一直干不出T2呢?为啥一直不会实现想法呢?还是想法本身就是错的呢?也许T3T4的dp是能做的但是时间都被T2耗完了,甚至T1差点都没了,真不知道二阶等差数列怎么整。
自闭了,进步空间巨大。
为什么大家都能场切省选题,场切CF*2900,为啥什么题都做过,啥都是“原题”
没关系,NOIP完就退役得了。
T1
推出来式子:,也就是 ,容易发现这是个二阶等差数列。通过知乎,得到求和公式是 ,带进去发现 再加上最后一段的和就对了。
T2
码力太差,思维太逊,死了。先按 排序,枚举每一个 作为中位数,求最多能买多少个物品。考虑对 值在其前后的数分别开一颗权值线段树,将 加到 的位置上,然后二分左右各取 个数,加上两颗权值线段树上前 个 ,再加上当前作为中位数的物品的 ,看有没有大于 ,若没有则更新 。最后 显然要取后缀最大值。
我的问题,没有实力。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls now<<1
#define rs now<<1|1
const ll N=1000005,M=1919810,mod=998244353;
struct val_tree{
ll sum[4*N],num[4*N];
void update(ll now,ll l,ll r,ll x,ll k){
sum[now]+=x*k;
num[now]+=k;
if(l==r) return;
ll mid=(l+r)>>1;
if(x<=mid) update(ls,l,mid,x,k);
else update(rs,mid+1,r,x,k);
}
ll query(ll now,ll l,ll r,ll x){
if(sum[now]<x) return mod;
if(l==r) return l*x;
ll mid=(l+r)>>1;
if(x<=num[ls]) return query(ls,l,mid,x);
return query(rs,mid+1,r,x-num[ls])+sum[ls];
}
}t1,t2;
ll n,m,T,ans[N];
struct xx{
ll w,v;
}a[N];
bool cmp(xx x,xx y){
return x.v^y.v?x.v<y.v:x.w<y.w;
}
bool check(ll i,ll mid){
return (t1.query(1,1,1e6,mid)+t2.query(1,1,1e6,mid)+a[i].w<=m);
}
/*和具体的价值没有关系,只关心大小关系*/
int main(){
freopen("gift.in","r",stdin);
freopen("gift.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m>>T;
ans[n+1]=-1;
for(int i=1;i<=n;++i) cin>>a[i].v>>a[i].w,ans[i]=-1;
sort(a+1,a+n+1,cmp);
for(int i=2;i<=n;++i) t2.update(1,1,1e6,a[i].w,1);
for(int i=1;i<=n;++i){
ll l=0,r=min(i-1ll,n-i),res=0;
while(l<=r){
ll mid=(l+r)>>1;
if(check(i,mid)) l=mid+1,res=mid;
else r=mid-1;
}
//cout<<"??? "<<res<<'\n';
ans[res]=a[i].v;
if(i!=n){
t2.update(1,1,1e6,a[i+1].w,-1);
t1.update(1,1,1e6,a[i].w,1);
}
}
for(int i=n;i>=1;--i) ans[i]=max(ans[i],ans[i+1]);
while(T--){
ll q; cin>>q;
cout<<ans[q/2]<<'\n';
}
return 0;
}/*5 10 5
1 3
2 4
4 3
2 3
5 4
3
1
1
5
1
拥有蒟蒻的力量,退役是必然的
绝望了*/
T3
简略写一下。首先 dp 很好写出来(但我挂了),然后发现我们在移动区间的时候某个数的出现次数会 ,令当前位置为 ,上一个和 相同数的位置为 ,上上个为 ,易发现 要 , 要 。问题转化成:每次区间加 ,求权值和大于等于 的所有位置的 值的和。分块维护即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define lxl long long
const ll N=114514,M=1919810,B=401;
const lxl mod=1e9+7;
ll n,p,a[N],ns,nq,st[N],ed[N],bel[N];
ll las[N],bu[N];
lxl dp[N],sum[B][N],pr[B],tag[B],cnt[N];
void pushdown(ll id){
for(int i=st[id];i<=ed[id];++i)
sum[id][cnt[i]]=0,cnt[i]+=tag[id];
tag[id]=pr[id]=0;
}
void update(ll id){
for(int i=st[id];i<=ed[id];++i){
sum[id][cnt[i]]=(sum[id][cnt[i]]+dp[i-1])%mod;
if(cnt[i]<=p) pr[id]=(pr[id]+dp[i-1])%mod;
}
}
void modify(ll l,ll r,ll k){
ll lx=bel[l],rx=bel[r];
if(lx==rx){
pushdown(lx);
for(int i=l;i<=r;++i) cnt[i]+=k;
update(lx); return;
}
pushdown(lx),pushdown(rx);
for(int i=l;i<=ed[lx];++i) cnt[i]+=k;
for(int i=st[rx];i<=r;++i) cnt[i]+=k;
update(lx),update(rx);
for(int i=lx+1;i<rx;i++){
if(k==1){
(pr[i]-=sum[i][p-tag[i]])%=mod;
tag[i]++;
}
else{
tag[i]--;
(pr[i]+=sum[i][p-tag[i]])%=mod;
}
}
}
lxl query(ll l,ll r){
lxl ans=0;
ll lx=bel[l],rx=bel[r];
if(lx==rx){
pushdown(lx),update(lx);
for(int i=l;i<=r;++i)
if(cnt[i]<=p) ans=(ans+dp[i-1])%mod;
return ans;
}
pushdown(lx),update(lx);
pushdown(rx),update(rx);
for(int i=l;i<=ed[lx];++i) if(cnt[i]<=p) ans=(ans+dp[i-1])%mod;
for(int i=st[rx];i<=r;++i) if(cnt[i]<=p) ans=(ans+dp[i-1])%mod;
for(int i=lx+1;i<rx;++i) ans=(ans+pr[i])%mod;
return ans;
}
int main(){
freopen("home.in","r",stdin);
freopen("home.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>p; ++n;
ns=sqrt(n),nq=ceil(n*1.0/ns);
for(int i=1;i<=nq;++i){
st[i]=ns*(i-1)+1,ed[i]=min(ns*i,n);
for(int j=st[i];j<=ed[i];++j) bel[j]=i;
}
for(int i=2;i<=n;++i){
cin>>a[i];
las[i]=max(bu[a[i]],1);
bu[a[i]]=i;
}
dp[1]=1,modify(1,1,1),update(bel[1]);
for(int i=2;i<=n;++i){
ll l=las[las[i]],r=i;
if(las[i]!=1) modify(l+1,las[i],-1);
modify(las[i]+1,r,1);
dp[i]=query(1,r);
}
//for(int i=1;i<=nq;++i) cout<<st[i]<<" "<<ed[i]<<" "<<tag[i]<<" "<<pr[i]<<'\n';
//for(int i=1;i<=n;++i) cout<<cnt[i]<<" ";cout<<'\n';
cout<<(dp[n]%mod+mod)%mod;
return 0;
}/*5 2
1 3 3 2 4
分块维护dp
没有xht真的会活不下去的
拥有蒟蒻的力量,退役是必然的*/
T4
你妈的原题
可以死一死了………………
发现好多人都在颓,包括但不限于看奥运/三国杀/扫雷/MC/不认识的玩意儿,怎么都没个万元神的(
反正都垫底了,就算后两场运气上来都300+也救不回来了,老实学NOIP得了
总有一种讲课时讲的东西不难但是给的提单里面全是CF*3000左右的题
8.1
上午讲字符串,结果这个教练直接用最形式化的方式来讲,我都不清楚他这样搞的意义是什么,如果是要把人讲懂那确实是完全失败,相比前天讲课确实拉了,而且后面讲的时候也是按自动机的模式来讲的,也搞得没几个人弄懂,至少我感受到的是这样的,几乎没有人在和他互动。一上午最大的收获是看完了《龙族Ⅱ》,这还不如再给我安排一场模拟赛,真心不如自己上网搜博客。
下午讲贪心,比上午好。不过不知道为什么到了后面也感觉没多少人在听……可能是贪心确实是比较迷的东西吧,这东西也只能挑一堆题出来讲了。
晚上做串串题,被牵着鼻子走,还是感觉莫名的时间少?磨一磨的就要十点了,很奇怪,也许是我时间观念不强?
回忆了一下 Manacher,还是没学Z函数,看到啥都想哈希。
不过看见了有人玩星铁。希望明天别挂分了,虽然就算两天都300+也只能老实呆在NOIP组了。
8.2
还没结束就来写了。
有星铁题,但是更寄了。不会T1,T2最后10min发现看错题,T3T4没想过正解,死了。
每一天都不会好
T1
玩粥玩的
考虑记忆化搜索,记录当前总共抽数,保底垫了多少抽,攒了多少星辉。搜索的时候记录下当前状态的答案,在每次递归的时候判断每种卡出的概率,然后就,没了。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define db double
const ll N=100005,M=1919810;
const db b3=40.0/98.0,b4=50.0/98.0,b5=8.0/98.0;
const db eps=1e-9;
ll nx;
db ans[405][105][305];
//总共抽数,垫了多少抽,有多少星辉
ll get(ll x){
if(x<10) return 0;
if(x<28) return 1;
if(x<68) return 3;
if(x<138) return 8;
if(x<258) return 18;
return 38;
}
db dfs(ll dep,ll x,ll y){
if(ans[dep][x][y]) return ans[dep][x][y];
ll tot=nx+get(y);
if(tot<dep) return 0;
db res=0;
db p6=0.02; p6+=0.02*max(x-50,0);
db p5=(1.0-p6)*b5,p4=(1.0-p6)*b4,p3=(1.0-p6)*b3;
if(p3>eps) res+=p3*dfs(dep+1,x+1,y);
if(p4>eps) res+=p4*dfs(dep+1,x+1,min(y+1,258));
if(p5>eps) res+=p5*dfs(dep+1,x+1,min(y+6,258));
res+=p6*0.65*dfs(dep+1,1,min(y+10,258));
res+=p6*0.35; ans[dep][x][y]=res;
return res;
}
int main(){
freopen("allin.in","r",stdin);
freopen("allin.out","w",stdout);
//ios::sync_with_stdio(0);
//cin.tie(0); cout.tie(0);
cin>>nx;
printf("%0.6lf",dfs(1,1,0));
return 0;
}/*事实证明,每个明天都不好
但只要有xht,一切都会好起来的*/
T2
dp,难受,不想补
T3
由题解分享发现可以随机化搞过去,考虑设阈值 ,对于编号小于等于 的边暴力遍历当前树中有哪些点,找到对应在树外的点连边。对于编号大于等于 的边暴力遍历有哪些点不在树中,找到对应在树中的点连边。对应中间部分的边考虑随机化,每次随机到可以与树中的点相连的点,然后就行了。期望时间复杂度 , 取 时最优。
这样建边的正确性可以证,因为整棵树当前只要有合法的连边,直接连边是一定不会使最后无解的,或者说怎么构造都有解,考虑反证法:
说句闲话,题面中的“存护”打错了,建议琥珀王敲一锤就老实了。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define lxl long long
#define db double
const ll N=1000005,M=1919810;
ll p,B,a[N],fa[N];
bool fl[N];
ll s[N],top;
mt19937 ra(19260817);
int main(){
freopen("company.in","r",stdin);
freopen("company.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>p; B=pow(p+1,2.0/3);
//cout<<B<<'\n';
for(int i=1;i<p;++i) cin>>a[i];
fl[0]=1;
for(int i=1;i<p;++i){
if(i<=B){
for(int j=0;j<i;++j)
if(!fl[(fa[j]+a[i])%p]){
fa[i]=(fa[j]+a[i])%p;
fl[fa[i]]=1;
cout<<fa[j]<<" "<<fa[i]<<'\n';
break;
}
}
else if(i>=p-B){
if(!top){
for(int j=1;j<p;++j)
if(!fl[j]) s[++top]=j;
}
for(int j=1;j<=top;++j)
if(!fl[s[j]]&&fl[(s[j]-a[i]+p)%p]){
fa[i]=s[j];
fl[s[j]]=1;
cout<<(s[j]-a[i]+p)%p<<" "<<fa[i]<<'\n';
break;
}
}
else{
ll x=0;
while(!fl[x]||fl[(x+a[i])%p]) x=ra()%p;
fa[i]=(x+a[i])%p;
fl[fa[i]]=1;
cout<<x<<" "<<fa[i]<<'\n';
}
}
return 0;
}/*7
3 1 1 4 4 4
玩星铁玩的*/
T4
直接暴力哈希是可以拿30pts的,但是,我他妈是个大智障然后没拿到……
正解有点复杂。
真的有点不想玩了,还有前两天一直憋着真的伤害挺大的,看来还是得有点划水,要不然要疯掉的。
8.3
阿巴阿巴
感觉写题也不行了,来写这个。反正都在分都挂了,就老实在NOIP呆着就行了,安稳当个废柴争取拿个联赛一等退役就行了/ng
反正何姐都放弃我了,来过两次机房,和所有人都问过模拟赛情况,除了我,这不就明摆着已经放弃了嘛。反正我本来就是给妹中推后腿的,早点退役自己心里也踏实,早点去学文化课出路肯定比继续坐牢竞赛大得多,况且虽然我whk成绩不好,但还对其不太厌恶,甚至我还有点觉得高中数学比较有意思,至少比那些傻逼的死板的难想的无趣的狗日的初中傻逼平几题要有趣,高数也有意思。物化生也比较感兴趣,最烦的是思政和语文。不过好像除了这两科别的我都有些兴趣?
无所谓喽,退役是迟早的事,只不过把它提前一年而已,然后就可以获得高中期间的全额分寒暑假和其他大部分节假日休假,不用在机房坐牢打题,挺好的。
但是,但是,我真他妈还想再拿个联赛一等,但是我他妈有这个实力吗我他妈有这个实力吗吗吗
我不到啊
妈的妈的想这么多干什么,明天打完模拟赛下午爽玩就行了,打多高多低都无所谓了,反正再高都只能呆在NOIP组,而且就算进了省选组我也会主动降下来的,毕竟天赋和实力摆在那里。打得高下午就爽完,打得低就郁闷着玩,反正打了就打了,我把总结写了题记了他就和我无瓜了。但是还是想下周在唐氏儿中当一个唐氏儿の王。
正题:今天上午数据结构,听了一点题,但是这个人除了平衡树其他的算法本题都基本没讲,然后直接甩题上来。下午是数学,其实单看PPT总结得挺好的,但是这个人讲课是真的不行,根据观察,全场可能就十个左右在听他讲,认真听的不到十个,然后就偷回机房颓废了。但是有一说一,私以为坐在机房写写题然后小小颓一下比坐在那里一直看小说看到脖子疼要有意义多了。
下课了,不写了
8.4
没写出任何题以及暴力,选择不报名比赛,迎来第一周的结束
T1
不
T2
不
T3
不
T4
不
准备下午颓废,已经放弃了上进的心,不管那些了。刚刚何姐叫我们下课后出去,应该是说分组,反正也和我没关系了,当自己把自己看作废柴时,自己的下限就会变得深不见底。
题是做的最少的,天赋也是最差的,训练时间也是最少的,傻逼才会继续学下去,是时候该滚了
他妈的还有牵挂,能有什么牵挂,早点退了就一身轻松了
/ll/ll/ll/ll/ll/ll/ll/ll/ll/ll
妈的哪个傻逼还想当唐氏儿の王,自己就是唐中之唐,垃圾中的垃圾,盘子都没有,桌子都掀不起来,什么都做不到,只配当炮灰给别人的 rk++,不如直接不打了顺便拉个人下水,盒盒盒盒盒盒盒盒盒盒盒盒盒盒盒盒盒盒盒盒
脑子已经胡成一团了
W1总结
原本是王写的,感觉很有启发性,遂来写。
挂分纪实
挂分指除实力不够想不到做法或实现不出来代码或者写得常数大或有 corner case 没有考虑到等赛后独自想也不一定想得出来修改方法的情况导致的丢分以外的情况。
D1:
没删调试语句
读题问题,对于可能理解出误差的地方一定要仔细去读,不要扫一眼就忙起写,理解错题意
要算数组空间是否开得下,不要乱开大,还要注意 预留空间,不要当牢大
D2:
暴力尽量打快点,留一点时间出来造几组数据验证一下正确性。对,暴力也要验证,除非是那种裸得不能再裸的。
D3:
打代码的过程中就要检查有没有哪里出错,一口气写完可能要调很久,反而更浪费时间。
如果能看出一个东西是dp,一定要从最暴力的dp入手,一步步的优化,可以考虑改变状态。
构造题可以随机化乱搞
D4:
一定要有良好的时间规划,一道题做到一定时间赶紧扔,所以一定要提前打暴力垫底,这样后面的题也有时间
一开始不觉得,但一定要用 10~15min 通读四道题,判断题目难度和大概能得的分,确定开题顺序。
8.5
孤独地当个小丑,唐氏儿。
欸我怎么直到 8.10 才来写后面的东西啊
8.6
W2 的 NOIP 第一场,rk28,感觉实力就这样了。
T1是二分答案+状压 dp,真的是不会了。T2智慧计数更不会,T3倒是树剖板题就会了,T4是ds赛时只会打暴力,T1和T4都挂了10pts,但加上20pts也只有rk19,实力就这样了/ll/ll/ll
8.7
好像是上午做了会儿反悔贪心题,然后去蹭课,下午又模拟赛,脑子没问题不挂分是能至少127pts,排在rk13的,但是T1因为傻逼数组记录坐标,然后差分中跳行了,导致死了,然后换成vector就80pts,关键是我一开始就想的是vector,甚至都开始写了,但是神他妈不知道怎么回事就换成数组了,淦,这个错我记下了。
这场难度比较大,T1二分答案+bfs,考验码力,T2神奇线头(?)dp,T3稍微可做一点,但也是智慧贪心,T4是CF*3500数据结构,鬼才会去写,但暴力16pts明明是读懂题就会的啊啊啊,都怪T1浪费我那么多时间,不,应该是怪我自己是个傻逼。
8.8
记不得干了啥。
8.9
坐在gcx旁边一起打比赛,然后就rk1了?不过这场的难度确实是最小的一场。T1简单数学,T2一个还算有启发性的题,T3区间dp,但是数据太水导致贼简单的贼容易hack的 贪心能拿90pts,谔谔。T4是差分,主要是没时间想了就打了暴力。最好的决策应该是把T1 T2 T4切了然后T3打暴力。
宋symbol:这个rk1的学校是什么啊?(指我写的“私立常盘台中学校”,整个人社死了,谁他妈想到就rk1了)
晚上看龙族4,颓废。
8.10
结束嘞
还不想写总结