1. 程式人生 > >Codeforces Round #516 (Div.2) A-E 題解

Codeforces Round #516 (Div.2) A-E 題解

交錯的fst


令我非常膜拜出題人的一場div.2,D題不愧為神題,這題不去做一下不是好漢.

圖片欣賞

在這裡插入圖片描述
機房裡一半都掛了D題.果然我還是最菜了.

過程

先迅速A掉AB兩題,看看C題,暫時不會,跳D題,發現D題是個sb搜尋題,10分鐘寫出來竟然 p p

pp 了,然後我成為了全場第二個ppD題的人.
接下來想想C題,發現C題果然是個sb題,迅速通過.
然後去研究E題,並用二分通過.
接下來我不禁開始思考D題有沒有什麼鍋.
最後兩分鐘我發現直接bfs搜到的不一定最優,這時已經來不及了.
熱烈祝賀一波 _ _ 123456 _ _
\_\_123456\_\_
倒一!

A

把三個數排序一下,看看較小兩個數加起來和大的數相差多少和 0 0 取個 max

\max 即可.

B

a b = a   x o r   b , b a a-b=a\ xor \ b,b\in a .
答案即為 1 < < p o p c o u n t ( x ) 1<<popcount(x) 也即 2 x 1 2^{x的二進位制中1的個數} .

C

大膽猜想,小心求證.
可以發現將相同的字母堆在一起顯然不會使迴文串的個數減少,因此只要直接對原字串排序即可.

D

用普通bfs會GG.
那麼如何保證延伸的時候一定會延伸到最優的結果呢?
我們用雙端佇列來處理bfs.
當上下移動的時候我們就把這個 n o d e node 放到隊頭,否則放到隊尾.
這樣就可過了.

#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

二分.
首先我們把一半的點放在直線 y = 1 y=1 上,每次取中間點,給黑色往左,白色往右.
一半點給完之後確定黑白分界線的一個端點.
然後把剩下一半點放在直線 x = 1 x=1 上,用同樣的方式操作.
最後將確定好的直線的兩個端點輸出.

#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);
}

謝謝大家.