Codeforces Round #516 (Div.2) A-E 題解
阿新 • • 發佈:2018-11-10
交錯的fst
令我非常膜拜出題人的一場div.2,D題不愧為神題,這題不去做一下不是好漢.
圖片欣賞
機房裡一半都掛了D題.果然我還是最菜了.
過程
先迅速A掉AB兩題,看看C題,暫時不會,跳D題,發現D題是個sb搜尋題,10分鐘寫出來竟然
了,然後我成為了全場第二個ppD題的人.
接下來想想C題,發現C題果然是個sb題,迅速通過.
然後去研究E題,並用二分通過.
接下來我不禁開始思考D題有沒有什麼鍋.
最後兩分鐘我發現直接bfs搜到的不一定最優,這時已經來不及了.
熱烈祝賀一波
倒一!
A
把三個數排序一下,看看較小兩個數加起來和大的數相差多少和 取個 即可.
B
.
答案即為
也即
.
C
大膽猜想,小心求證.
可以發現將相同的字母堆在一起顯然不會使迴文串的個數減少,因此只要直接對原字串排序即可.
D
用普通bfs會GG.
那麼如何保證延伸的時候一定會延伸到最優的結果呢?
我們用雙端佇列來處理bfs.
當上下移動的時候我們就把這個
放到隊頭,否則放到隊尾.
這樣就可過了.
#include<bits/stdc++.h> //lthea Myse Valgulious
using namespace std;
const int aoi=2018,d[]={1,0,-1,0,0,1,0,-1};
char mp[aoi][aoi];
int n,m,r,c,lx,ly,vis[aoi][aoi];
struct node{
int x,y,lt,rt;
};
void bfs(int sx,int sy){
deque<node> q;
q.push_back(node{sx,sy,0,0});
vis[sx][sy]=1;
for (;!q.empty();){
node u=q.front(); q.pop_front();
for (int i=0;i<4;++i){
int nx=u.x+d[i],ny=u.y+d[i+4];
int nlt=u.lt+(i==3),nrt=u.rt+(i==1);
if (nx>0&&nx<=n&&ny>0&&ny<=m&&mp[nx][ny]^'*'&&nlt<=lx&&nrt<=ly&&!vis[nx][ny]){
vis[nx][ny]=1;
if (i&1) q.push_back(node{nx,ny,nlt,nrt});
else q.push_front(node{nx,ny,nlt,nrt});
}
}
}
}
int main(){
int i,j,llx=0;
n=read(),m=read();
r=read(),c=read();
lx=read(),ly=read();
for (i=1;i<=n;++i) scanf("%s",mp[i]+1);
bfs(r,c);
for (i=1;i<=n;++i)
for (j=1;j<=m;++j) llx+=vis[i][j];
write(llx);
}
E
二分.
首先我們把一半的點放在直線
上,每次取中間點,給黑色往左,白色往右.
一半點給完之後確定黑白分界線的一個端點.
然後把剩下一半點放在直線
上,用同樣的方式操作.
最後將確定好的直線的兩個端點輸出.
#include<bits/stdc++.h> //lthea Myse Valgulious
using namespace std;
const int mulu=1e9;
int main(){
int i,j,n=read();
if (n==1){
cout<<"1 1"<<endl;
cout<<"3 3 6 3"<<endl;
return 0;
}
ll l=1,r=mulu-1;
for (i=1;i<=(n>>1);++i){
ll mid=(l+r)>>1;
cout<<mid<<" "<<1<<endl;
string s; cin>>s;
s.front()=='b'?r=mid-1:l=mid+1;
}
ll t=l+1;
l=1,r=mulu-1;
for (n-=n/2,i=1;i<=n;++i){
ll mid=l+r>>1;
cout<<1<<" "<<mid<<endl;
string s; cin>>s;
s.front()=='b'?r=mid-1:l=mid+1;
}
printf("%lld %lld %lld %lld\n",1ll,l+1,t,1ll);
fflush(stdout);
}
謝謝大家.