Nov 20
今天依然是爆炸的一天,第一题因为使用了下标访问了 map 而导致了 tle, T1 直接 100 -> 60,觉得写一些赛后总结会好很多,最近也不想写什么题了,于是便总结总结吧。
比赛经验上的
似乎真的有 OI 教练模拟器的虎头蛇尾的 tag 了,只有比赛开始的一个小时能够正常的思考。
感觉对于我来说集中注意力一个小时以上很困难。
之后尝试给自己留十几分钟休息时间试一下。
到现在我才知道了运行代码的时候可以通过 time ./文件名 来知道我的文件运行时间,感谢 langmouren 的告知,我之前一直使用 clock(),这个样子似乎确实方便一些。
不知道有没有什么静心的方法,今天晚上学习一下冥想。
最近的题似乎难度普遍的低了一些,似乎想练习我的的做题习惯?今天似乎 T2 最难。
没了。
题目上的
T1 S2OJ 33
水题。
看起来不是 dp 就是贪心。
发现斐波那契数列的增长极度快速,在第四十多项就会达到 2e9 级别,是可以枚举判断的。
我们发现了一个性质,就是一次划分的贡献为一,这个性质通常可以导向贪心。
我们考虑一下从左向右扫,能放到当前段的就放,任何冲突都会导致划分到不同两个段中,贡献不变,贪心正确。
而我使用了 map 维护当前段中的值出现情况,但是使用 [] 访问,所以 tle 了,改成 .count() 查询就好了。
代码↓
点击查看代码
#include <bits/stdc++.h>
#define getchar getchar_unlocked
#define int long long
using namespace std;
const int MN=1e5+115;
int f[MN], a[MN], n;
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*10+ch-'0',ch=getchar();
return x*f;
}
void Read(){
n=read();
for(int i=1; i<=n; ++i) a[i]=read();
return;
}
unordered_map <int,int> exist;
void Solve(){
Read();
int ans=0;
for(int i=1; i<=n; ++i){
if(exist.empty()){
ans++; exist[a[i]]=true;
continue;
}
for(int j=1; j<=45; ++j){
if(exist.count(f[j]-a[i])){
ans++;
exist.clear();
break;
}
}
exist[a[i]]=true;
}
cout<<ans<<'\n';
return;
}
signed main(){
//clock_t Begin, End;
//double duration; Begin=clock();
//freopen("f.in","r",stdin);
//freopen("f.out","w",stdout);
f[0]=0; f[1]=1;
for(int i=2; i<=50; ++i) f[i]=f[i-1]+f[i-2];
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
Solve();
//End=clock();
//duration=double(End-Begin)/CLOCKS_PER_SEC;
//cout<<"tick="<<double(End-Begin)<<endl;
//cout<<"运行时间: "<<duration<<"s"<<endl;
return 0;
}
/*
回家想玩游戏打开卡兹天梯
带上我的日快闪击 所向无敌
来到对局第一把是炸槽的霓虹兵
习志野 35t 中消防局都打一
穷兵加上亡命之计
我疲软无力 阔土大飞机
再出山本八乘七
面对如此这般强敌
我只能右上角逃逸
*/
T2 S2OJ 34
神秘题。
有两个对于中位数的限制,不太好搞的样子。
问题需要知道中位数的一些小性质。
如果区间中位数 \(\le\) x。
我们可以得到了 (区间中\(\le\) x 的元素个数) \(\ge\) (区间中大于 x 的元素个数)
然而介个有神马用呢?
我们考虑一个区间的中位数 \(\le\) val
使用一次前缀和求出来每一个位置。
对于 \([j+1,i]\) 区间中。
\(\le\) val 的元素个数 cnt=sum[i]-sum[j]
\(>\) val 的元素个数是 (i-j)-cnt
我们按照中位数性质可以化简出来
2 * sum[i] - i \(\ge\) 2 * sum[j] - j
我们每一次存一下就好了,我们就扫一下,树状数组维护,没有了,好题一个。
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define getchar getchar_unlocked
using namespace std;
const int MN=1e6+116;
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*10+ch-'0',ch=getchar();
return x*f;
}
struct BIT{
int tr[MN], n=MN;
void init(){
memset(tr,0,sizeof(tr));
}
int lowbit(int x){
return x&(-x);
}
void update(int pos, int val){
pos+=2e5+215;
for(int i=pos; i<=n; i+=lowbit(i)) tr[i]+=val;
return;
}
int qval(int pos){
int res=0; pos+=2e5+215;
for(int i=pos; i; i-=lowbit(i)) res+=tr[i];
return res;
}
}tr;
int sum[MN], n, a[MN];
int Get(int pos, int l, int r){
tr.init(); memset(sum,0,sizeof(sum));
for(int i=1; i<=n; ++i){
sum[i]=(sum[i-1]+(a[i]<=pos));
}
int res=0; ++r;
for(int i=l; i<=n; ++i){
tr.update(2*sum[i-l]-(i-l),1);
if(i>=r) tr.update(2*sum[i-r]-(i-r),-1);
res+=tr.qval(2*sum[i]-i);
}
return res;
}
void Read(){
n=read(); for(int i=1; i<=n; ++i) a[i]=read();
}
void Solve(){
Read(); int q; q=read();
while(q--){
int l1, r1, l2, r2;
l1=read(); r1=read();
l2=read(); r2=read();
cout<<Get(r1,l2,r2)-Get(l1-1,l2,r2)<<'\n';
}
return;
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
Solve();
return 0;
}
T3 S2OJ 35
人类智慧题。
发现两个点可以互相到达当且仅当两个点所属的矩形集合相同。
考虑哈希,需要可以删除,考虑异或哈希,给每一个矩形一个随机值。
使用二维树状数组维护,就没有了,很简单,但我场上并没有看这道题。
代码↓
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define getchar getchar_unlocked
using namespace std;
const int MN=3555;
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*10+ch-'0',ch=getchar();
return x*f;
}
struct BIT{
int n, m, tr[MN][MN];
int lowbit(int x){
return x&(-x);
}
void update(int x, int y, int val){
for(int i=x; i<=n; i+=lowbit(i)){
for(int j=y; j<=m; j+=lowbit(j)){
tr[i][j]^=val;
}
}
}
int qval(int x, int y){
int res=0;
for(int i=x; i; i-=lowbit(i)){
for(int j=y; j; j-=lowbit(j)){
res^=tr[i][j];
}
}
return res;
}
}tr;
int n, m, q;
struct Node{
int x1, x2, y1, y2;
bool operator <(const Node &o)const{
if(x1!=o.x1) return x1<o.x1;
if(x2!=o.x2) return x2<o.x2;
if(y1!=o.y1) return y1<o.y1;
return y2<o.y2;
}
};
map <Node,int> hashed;
void Solve(){
n=read(); m=read(); q=read();
tr.n=n; tr.m=m;
for(int i=1; i<=q; ++i){
int op, x1, y1, x2, y2;
op=read(); x1=read(); y1=read();
x2=read(); y2=read();
if(op==1){
int key=rand();
tr.update(x1,y1,key);
tr.update(x1,y2+1,key);
tr.update(x2+1,y1,key);
tr.update(x2+1,y2+1,key);
hashed[{x1,x2,y1,y2}]=key;
}else if(op==2){
int key=hashed[{x1,x2,y1,y2}];
tr.update(x1,y1,key);
tr.update(x1,y2+1,key);
tr.update(x2+1,y1,key);
tr.update(x2+1,y2+1,key);
}else{
if(tr.qval(x1,y1)==tr.qval(x2,y2)) cout<<"Yes\n";
else cout<<"No\n";
}
}
return;
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
Solve();
return 0;
}
T4 S2OJ 112
哈基米曼波题。
发现数据范围很小,但并没有小到可以直接暴力搜索。
不过如果要爆搜,范围需要小一半,我们考虑 meet in middle。
跑出来所有的集合,sort 一下,二分答案进行合并。
一定不要忘记在每一个几个内部进行答案统计。
代码↓
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define getchar getchar_unlocked
using namespace std;
const int MN=44;
vector <int> a, b;
int n, m, s[MN], ans=0;
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*10+ch-'0',ch=getchar();
return x*f;
}
void Read(){
n=read(); m=read();
for(int i=1; i<=n; ++i) s[i]=read();
return;
}
void dfsl(int l, int r, int sum){
if(l>r){
a.emplace_back(sum);
ans=max(ans,sum%m);
return;
}
dfsl(l+1,r,sum);
dfsl(l+1,r,(sum+s[l])%m);
return;
}
void dfsr(int l, int r, int sum){
if(l>r){
b.emplace_back(sum);
ans=max(ans,sum%m);
return;
}
dfsr(l+1,r,sum);
dfsr(l+1,r,(sum+s[l])%m);
return;
}
void Solve(){
Read(); int mid=n/2;
dfsl(1,mid,0); dfsr(mid+1,n,0);
sort(a.begin(),a.end());
sort(b.begin(),b.end());
for(auto v:a){
int k=*(upper_bound(b.begin(),b.end(),m-v-1)-1);
ans=max(ans,(v+k)%m);
}
cout<<ans<<'\n';
return;
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
Solve(); return 0;
}
希望明天的比赛我可以打好。

浙公网安备 33010602011771号