第一周记
第一周
前言:
10.17
停了这么长时间也是也是有幸回归了,目前应该是会作为 \(ACMer\) 继续走下去了吧。很多感慨的话啊,之后也许会单开一帖好好讲讲的吧。言归正传,从今天起每周补一到两场比赛吧,这个系列的主要目的是记录一周的题解和感想吧,也许有点类似“周记”的味道吧。但是怎么写还真是一团乱麻,说真的,我要写给谁看啊(笑,大概是只有自己看了,那就不用注意什么格式了吧,这还挺好的。
为了激励自己防止自己颓废特意整了半天博客美化,但是又怎样才可以搞一个目录索引啊,感觉乱糟糟的。
新同志们感觉有几个厉害的大神啊,这样也挺好,要不然只有我是所谓的“有基础”感觉怪怪的,隔壁的 \(lzh\) 代码能力是 \(7\) 级欸,(但是南方同志讲话我总是听不清怎么办啊呜呜呜)好厉害。
其实感觉自己这段时间做的又好又不好啊,晚上看漫画熬的有点晚(不过喰种真好看),而且上水课的时候也没什么心思学别的,要改要改。不过好的地方是做题感觉有点节奏了(虽然还是很菜),认识到之前学的菜是因为太爱乱学算法了,感觉当时有点卖弄的心理,没有意识到基础的重要性(这话被我妈听到又要长篇大论了),不去练思维题,不练基础算法果然不行,总之经历了高考心态成熟了不少吧,现在认识到也不算太晚嘛。
总体来说还是相信自己的,下周一定要重整旗鼓啊,不能颓废了,你也不打游戏有什么好沉迷的,要学的也就数学英语吧,这总比高中轻松多了,我不信还学不好。
话说快考试了,我总是害怕考试呢,考试这个东西很奇怪啊,你永远也不可能在客观上把一场考试完全充分的准备好,但是你可以在主观上充分准备,当你合理的调节主观的期望成绩与复习准备的平衡时,往往就能取得一个好成绩。但是我总是很不擅长这种调节呢。
哦哦还有四级听力,我感觉好难啊,感觉也就能听出来十分之一吧,诶诶,我记得高中时我的英语也是一百三四的水平啊。
这个周末要卷一卷了,做完作业后好好学学英语吧,也许没什么实际作用但是应该能增强底气吧,加油加油!
10.18
呃呃,周末 \(8\) 点起来补题,这次试一下跟着打比赛,遇到啥不会就学啥,也许这样比怼着专题练好的多吧。
下午去看 \(lcx\) 踢球,对面动力的脚有点脏,不过我们赢了就好。
刚刚写代码被班长看见了,有种孩子做错事一般的矛盾感,为什么会这样啊?其实让别人知道了你是“有基础”又能怎么样呢?总是害怕“小时了了,大未必佳”这种现象,其实也没个什么,动动脑子也知道这前后没什么必然联系吧。重要的是不要内耗,不论是做了错事还是做了好事,结束以后就应该立刻忘掉,最忌讳对已经过去的事耿耿于怀,妄自菲薄和妄自尊大皆不可,自己和自己共勉吧。
目前水平大概在”提高-“吧,菜是真的菜。
10.19
补了高数和英语作业,下午打了新生赛,切了 \(8\) 道, \(rank280\)(被罚了很多时,没太认真做),这周是没时间补题解了,下周吧。
周测做的很不好,感觉英语听力是有进步的,但是求极限还不是很会,下周加油。
睡觉了,第一周再见~~~
学习笔记
先补个比赛题解吧。
CCPC2024 邀请赛山东站
Problem A.打印机
直接对时间进行二分,然后很简单的 \(check\) 这里就不写了,注意上界开到 \(1e9\) 就可以过,我管你这那的直接开到 LLONGMAX。
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N=200;
int T,n,k;
int t[N],l[N],w[N];
bool check(int time){
int tot=0;
for(int i=1,x,y;i<=n;++i){
x=time/(t[i]*l[i]+w[i]);
y=time%(t[i]*l[i]+w[i]);
tot+=l[i]*x;
tot+=((y>=t[i]*l[i])?l[i]:y/t[i]);
}
return tot>=k;
}
signed main(){
cin>>T;
for(;T--;){
cin>>n>>k;
memset(t,0,sizeof(t));
memset(l,0,sizeof(l));
memset(w,0,sizeof(w));
for(int i=1;i<=n;++i) cin>>t[i]>>l[i]>>w[i];
int tot(0),time(0);
int l(0),r(2e18),mid,ans(0);
for(;l<=r;){
mid=l+(r-l)/2;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;
}
}
Problem C.多彩的线段 2
看了以后觉得似乎可以把重合的线段连在图上,当然要注意到可能会形成若干个互不连通的子图,这样就可以转化为图上相邻节点颜色不同的方案数,这应该就是图着色问题了,但是我不会。
既然这样那就只好考虑利用一下左右端点的特殊性质了。将线段按照左端点排序,然后扫点,边扫边统计前缀相连的的线段数 \(c_i\),则贡献答案为 \(k-c_i\)
然后这样是 \(n^2\) 的肯定不行,既然要查询前缀中右端点比当前线段左端点大的线段数量,那可以用权值树状数组维护一下。
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int p=998244353;
const int N=5e5+10;
int T,n,k;
struct Node{
int l,r;
}dat[N];
struct BT{
#define lowbit(x) (x&(-x))
int t[N];
void add(int pos,int v){
for(int i=pos;i<=n<<1;i+=lowbit(i)) t[i]+=v;
}
int sum(int pos){
int ans(0);
for(int i=pos;i;i-=lowbit(i)) ans+=t[i];
return ans;
}
}t;
void solve(){
cin>>n>>k;
vector<int> num((n<<1)+1);
memset(t.t,0,sizeof(t.t));
for(int i=1;i<=n;++i){
cin>>dat[i].l>>dat[i].r;
num[i]=dat[i].r;
num[i+n]=dat[i].l;
}
sort(dat+1,dat+n+1,[](Node &a,Node &b){return a.l<b.l;});
sort(num.begin(),num.end());
int gs(unique(num.begin(),num.end())-num.begin());
for(int i=1;i<=n;++i){
dat[i].r=lower_bound(num.begin()+1,num.begin()+gs,dat[i].r)-num.begin();
dat[i].l=lower_bound(num.begin()+1,num.begin()+gs,dat[i].l)-num.begin();
}
int ans(1);
for(int i=1;i<=n;++i){
int res(k);
res=res-(i-t.sum(dat[i].l-1)-1);
if(res<0) res=0;
t.add(dat[i].r,1);
ans=ans*res%p;
}
cout<<(ans+p)%p<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>T;
for(;T--;) solve();
return 0;
}
Problem F.分割序列
一般要求 \(i^p\times s_i\) 这种因子往往考虑多次前后缀,也算一种经典的 \(trick\) 吧。
看这一道题的话,考虑到后面的因数更大,那我们就先维护一个后缀和,然后贪心的找出最大的 \(k-1\) 的和项与序列总和求和,也就是求两次后缀和。
注意一些细节:显然当 \(k=1\) 时直接求总和,且总和不用参与排序。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,T,a[N];
signed main(){
for(cin>>T;T--;){
cin>>n;
memset(a,0,sizeof(a));
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=n;i;i--) a[i]+=a[i+1];
cout<<a[1]<<' ';
sort(a+2,a+n+1,greater<int>());
for(int i=2;i<=n;++i) cout<<(a[i]+=a[i-1])<<' ';
cout<<endl;
}
return 0;
}