1. 程式人生 > >【題解】Codeforces 1063:Round #516 (Div. 1, by Moscow Team Olympiad) ABC

【題解】Codeforces 1063:Round #516 (Div. 1, by Moscow Team Olympiad) ABC

總結

  1. 字串排序後的迴文子串數最多,為ΣNx(Nx+1)/2\Sigma N_x(Nx+1)/2
  2. bfs獲得下一步狀態時,選擇遍歷常數陣列與分別列舉中適合的方案。

A. Oh Those Palindromes 迴文串,結論

給定一個非空字串,求它的一個重排,使得迴文子串的數量最多。

結論:排序。

證明:每個迴文串的第一個與最後一個字元是相同的,如果字串中字元x出現了NxN_x次,那麼總的迴文子串個數必然小於等於ΣNx(Nx+1)/2\Sigma N_x(Nx+1)/2,而排序後的答案恰為這個值。

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.

等題解出來再補~