Shunpower @ 2022-05-17 17:16:05
在 这个帖子 中,除我以外的很多 OIer 都表示关同步流比 scanf/printf 快。
比如里面提到的这个例子:
这道题读入了
但是在 P8251 [NOI Online 2022 提高组] 丹钓战 这个题,您可以检索我的提交记录,这里放了其中五份:
这五份都是一模一样的使用关闭同步流读入的考试代码,前四份是我考完之后交的,第五份是我刚才交的。可以观察到最是有许多点 TLE。
但是当我们换为 scanf/printf 读入的时候,这份代码跑得快了很多:
第一份是我刚才交的,其他的都是我考后交的。都是一模一样的只是将前面那份代码的读入方式修改的代码,可以观察到完全是可以 AC 的而且与评测机波动 无关。
这道题的读入量最大为
这道题有 O2 优化,因此我的问题:
1.O2 是否影响读入方式的相对快慢,若影响,是否可以给出不同评测方式在 O2 下的速度排名?
2.是否可以给出“这么多的读入量适用的读入方式”的表?
3.解决这道题为什么 scanf/printf 快的问题。
相关内容:我的另一个帖子 关于 CCF 和你谷评测机差异和吸氧
代码二楼。
by Shunpower @ 2022-05-17 17:16:30
//Why Card My Simple Number?!!!!
//233
//I'm No-rain......
//555
//If I can't get my AC,I will cry.
//Thanks for your help,CCF!
#include <bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define fr1(i,x,y) for(int (i)=(x);i<=(y);(i)++)
#define fr2(i,x,y) for(int (i)=(x);i>=(y);(i)--)
#define mp(x,y) make_pair((x),(y))
#define debug puts("Chery AKs IOI")
using namespace std;
const int N=5e5+10;
int tnt;
struct node{
int a,b,id;
};
int n,q;
pii a[N];
//int maxb,nowm;
//map <int,int> ap;
int pre[N];
stack <node> s;
struct Segment_Tree{
int ls,rs,sum;
} k[N*80];
int rot[N];
int l,r;
inline void insert(int &p,int lastp,int l,int r,int idx){
if(!p){
tnt++;
p=tnt;
}
k[p].sum=k[lastp].sum;
k[p].sum++;
if(l==r){
return;
}
int m=(l+r)>>1;
if(idx<=m){
insert(k[p].ls,k[lastp].ls,l,m,idx);
k[p].rs=k[lastp].rs;
}
else{
insert(k[p].rs,k[lastp].rs,m+1,r,idx);
k[p].ls=k[lastp].ls;
}
// k[p].sum=k[k[p].ls].sum+k[k[p].rs].sum;
}
//void deb(int p,int l,int r){
//// cout<<p<<","<<l<<","<<r<<","<<k[p].sum<<endl;
// if(l==r){
// return;
// }
// int m=(l+r)>>1;
// deb(k[p].ls,l,m);
// deb(k[p].rs,m+1,r);
//}
inline int query(int p,int l,int r,int ml,int mr){
if(ml<=l&&r<=mr){
int x=k[p].sum;
// cout<<"hjl:"<<p<<","<<l<<","<<r<<","<<k[p].sum<<endl;
return k[p].sum;
}
int m=(l+r)>>1;
int ans=0;
if(ml<=m){
ans+=query(k[p].ls,l,m,ml,mr);
}
if(m<mr){
ans+=query(k[p].rs,m+1,r,ml,mr);
}
return ans;
}
int main(){
// freopen("stack.in","r",stdin);
// freopen("stack.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n>>q;
fr1(i,1,n){
cin>>a[i].fi;
}
fr1(i,1,n){
cin>>a[i].se;
}
// ap[a[1].fi]=1;
// maxb=a[1].se;
s.push({a[1].fi,a[1].se,1});
// nowm=1;
fr1(i,2,n){
while(!s.empty()){
if(s.top().a==a[i].fi||s.top().b<=a[i].se){
s.pop();
}
else{
break;
}
}
int x=s.empty()?0:s.top().id;
s.push({a[i].fi,a[i].se,i});
pre[i]=x;
}
fr1(i,1,n){
insert(rot[i],rot[i-1],0,n,pre[i]);
// cout<<"1111"<<endl;
// deb(rot[i],0,n);
}
// deb(rot[n],0,n);
// fr1(i,1,n){
// cout<<rot[i]<<" ";
// }
// puts("");
fr1(i,1,q){
cin>>l>>r;
cout<<query(rot[r],0,n,0,l-1)-query(rot[l-1],0,n,0,l-1)<<endl;
}
return 0;
}
//Everything For Ji
//Everything For Lin
//Everything For You
//Teens-in-Times HJL
//20040615 Forever.
by WYXkk @ 2022-05-17 17:22:20
@Zealous_YH 你的关同步相对于我知道的版本少写了两句 cin.tie(NULL);cout.tie(NULL);,可能是这个的问题吧?
by Shunpower @ 2022-05-17 17:25:59
@WYXkk
emm,那我再测测
by Dr_Gilbert @ 2022-05-17 17:26:48
@Zealous_YH
您好,使用endl将自动刷新缓冲区,如果频繁刷新缓冲区也会导致速度变慢,建议换成 \n 。同时请关闭绑定,效率更高。这是用我小号提交的,添加我所说几项的您的代码,可以看到是通过的。记录
添加的代码:
#define endl '\n'
...
cin.tie(nullptr)
cout.tie(nullptr)
by Shunpower @ 2022-05-17 17:28:05
@WYXkk
似乎还是不太行,80 pts
by Shunpower @ 2022-05-17 17:29:24
@Dr_Gilbert
thx,所以 endl 在关同步的情况下是不会被加速的吗?还是说优化非常少?
by Shunpower @ 2022-05-17 17:32:45
@Zealous_YH
在仅仅使用
cin.tie(nullptr)
cout.tie(nullptr)
的情况下,也只能获得
但是在不使用 endl 的情况下,确实可以 AC
所以希望可以解决一下关于 endl 的效率问题。
所以
endl在关同步的情况下是不会被加速的吗?还是说优化非常少?
by Dr_Gilbert @ 2022-05-17 17:32:55
@Zealous_YH 关不关同步和刷新缓冲区是两回事
by Shunpower @ 2022-05-17 17:34:57
@Dr_Gilbert
emm,因此 endl 与同步流无关对吧
ok,谢谢您!
by Shunpower @ 2022-05-17 17:35:32
好的 我明白了 此贴终,谢谢大家
这个题上的所有问题算是结束了