【題解】Codeforces 1063:Round #516 (Div. 1, by Moscow Team Olympiad) ABC
阿新 • • 發佈:2019-02-11
總結
- 字串排序後的迴文子串數最多,為
- bfs獲得下一步狀態時,選擇遍歷常數陣列與分別列舉中適合的方案。
A. Oh Those Palindromes 迴文串,結論
給定一個非空字串,求它的一個重排,使得迴文子串的數量最多。
結論:排序。
證明:每個迴文串的第一個與最後一個字元是相同的,如果字串中字元x出現了次,那麼總的迴文子串個數必然小於等於,而排序後的答案恰為這個值。
B. Labyrinth 01bfs
給定n*m(2000,2000)有空格與障礙的網格地圖,初始時在給定的某空格位置上,最多向左走x步,向右走y步,上下不限,問幾個格子是可達的?
拿queue去bfs會WA,拿priority_queue去bfs會TLE,注意到走一步的花費要麼為1(左右),要麼為0(上下),所以可以拿deque去bfs,即01bfs。
補完這套去訓練一下01bfs。。
還有一個寫碼問題:當bfs的方向區分不大時,可以預製const陣列。如果每個方向都有區分,最好分開寫if或者switch。
/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 2048, MOD = 1000000007;
int n,m,sx,sy,l0,r0;
struct Node
{
Node(int _x,int _y,int _l,int _r):x(_x),y(_y),l(_l),r(_r){}
int x,y,l,r;
};
deque<Node> dq;
char mp[M][M], vis[M][M];
inline void go(int x,int y,int l,int r,int t)
{
if(mp[x][y]=='.' && vis[x][y]==0 && l<=l0 && r<=r0)
{
vis[ x][y] = 1;
if(t) dq.emplace_back(x,y,l,r);
else dq.emplace_front(x,y,l,r);
}
}
int main(void)
{
#ifdef _LITTLEFALL_
freopen("in.txt","r",stdin);
#endif
scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&l0,&r0);
for(int i=1;i<=n;++i)
scanf("%s",mp[i]+1);
vis[sx][sy] = 1;
dq.emplace_front(sx,sy,0,0);
int ans = 0;
for(Node p=dq.front();!dq.empty();++ans)
{
p = dq.front(); dq.pop_front();
go(p.x+1,p.y,p.l,p.r,0);
go(p.x-1,p.y,p.l,p.r,0);
go(p.x,p.y+1,p.l,p.r+1,1);
go(p.x,p.y-1,p.l+1,p.r,1);
}
printf("%d\n",ans );
return 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;
}
C. Dwarves, Hats and Extrasensory Abilities 互動,二分
給出n(30),在1e9*1e9的座標平面上,每次提交一個座標,會得到一個字串表示這個座標上的點的顏色(黑白),確定n個點的顏色後,兩點式輸出一條直線將黑點與白點分開。
時刻保證左右顏色不同並記錄左右顏色的邊界,輸出邊界中間的點,然後根據顏色更新邊界。
可以做一條斜率為1e9的線來穿過差為1的兩個邊界。
/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 500016, MOD = 1000000007;
int save[M];
int main(void)
{
#ifdef _LITTLEFALL_
//freopen("in.txt","r",stdin);
#endif
int n = read()-1;
char tmp[20];
cout << 0 <<" "<< MOD/2 << endl;
scanf("%s",tmp);
int ori = tmp[0]=='w' ? 1:0; //白1黑0
int lef = 0, rig = 1000000000;
while(n--)
{
int mid = (lef + rig)>>1;
cout << mid <<" "<< MOD/2 << endl;
scanf("%s",tmp);
int tt = tmp[0]=='w' ? 1:0;
if(tt==ori) lef = mid;
else rig = mid;
}
printf("%d %d %d %d\n",lef,0,rig,1000000000 );
return 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;
}
D. Candies for Children 分類,列舉+check
n個人圍成一圈從1到n編號,k個糖果,順時針輪流拿糖果,糖果盒遞給編號l的人,編號為r的人拿走了最後的糖果。不愛吃甜食的人或者糖果盒裡只有一顆糖果時會拿一顆,其他愛吃甜食的人會拿兩顆。問最多有幾個愛吃甜食人,無解時輸出-1.
等題解出來再補~