二分答案 Packmen CodeForces

来源:互联网 发布:蒙古语翻译软件 编辑:程序博客网 时间:2024/06/05 05:30

感谢博客:https://www.cnblogs.com/zgglj-com/p/7689462.html
题目提交地址:https://cn.vjudge.net/problem/CodeForces-847E

Packmen CodeForces - 847E
A game field is a strip of 1 × n square cells. In some cells there are Packmen, in some cells — asterisks, other cells are empty.

Packman can move to neighboring cell in 1 time unit. If there is an asterisk in the target cell then Packman eats it. Packman doesn’t spend any time to eat an asterisk.

In the initial moment of time all Packmen begin to move. Each Packman can change direction of its move unlimited number of times, but it is not allowed to go beyond the boundaries of the game field. Packmen do not interfere with the movement of other packmen; in one cell there can be any number of packmen moving in any directions.

Your task is to determine minimum possible time after which Packmen can eat all the asterisks.

Input

The first line contains a single integer n (2 ≤ n ≤ 105) — the length of the game field.

The second line contains the description of the game field consisting of n symbols. If there is symbol ‘.’ in position i — the cell i is empty. If there is symbol ‘*’ in position i — in the cell i contains an asterisk. If there is symbol ‘P’ in position i — Packman is in the cell i.

It is guaranteed that on the game field there is at least one Packman and at least one asterisk.

Output

Print minimum possible time after which Packmen can eat all asterisks.

Example

Input
7
..P*P
Output
3
Input
10
.*PP.*P.
Output
2
Note

In the first example Packman in position 4 will move to the left and will eat asterisk in position 1. He will spend 3 time units on it. During the same 3 time units Packman in position 6 will eat both of neighboring with it asterisks. For example, it can move to the left and eat asterisk in position 5 (in 1 time unit) and then move from the position 5 to the right and eat asterisk in the position 7 (in 2 time units). So in 3 time units Packmen will eat all asterisks on the game field.

In the second example Packman in the position 4 will move to the left and after 2 time units will eat asterisks in positions 3 and 2. Packmen in positions 5 and 8 will move to the right and in 2 time units will eat asterisks in positions 7 and 10, respectively. So 2 time units is enough for Packmen to eat all asterisks on the game field.

题解:二分时间,然后检查答案(emmmmm,然而check不会写),借鉴大佬的代码(》《)

官方:这是 codeforces 343c Read Time的题解,不过和这道题是相同的解法

Let’s search the answer t with the binary search. Fix some value of t. Look at the first head from the left h[i] that can read track p[0]. If p[0] > h[i], then h[i] goes to the right t seconds and reads all tracks on its way. Otherwise if p[0] ≤ h[i], then the head has two choices:

go to the right seconds, then to the left and h[i] - p[0] again to the left;
go to the left h[i] - p[0] seconds, then h[i] - p[0] to the right and t - 2·(h[i] - p[0]) again to the right.
Obviously, for h[i] it is more advantageous to visit the track positioned as much as possible to the right. So we choose by . Then we move the pointer onto the first unread track, and repeat the algorithm for h[i + 1], and so on with each head.

我们用二分查找搜索答案。 修正t的一些值。 看看左边的第一个磁头h [i],它可以读取磁道p [0]。 如果p [0]> h [i],那么h [i]会在右边t秒读取所有曲目。 否则,如果p [0]≤h [i],那么头有两个选择:

转到右边的秒,然后到左边,h [i] - p [0]再次转到左边;
再次向右移动h [i] -p [0]秒,然后向右移动h [i] -p [0],再向右移动t-2·(h [i] -p [0])。
显然,对于我来说,访问尽可能多的轨道是更有利的。 所以我们选择。 然后我们将指针移动到第一条未读的轨道上,并重复h [i + 1]的算法,以此类推。

#include<bits/stdc++.h>using namespace std;const int maxn=1e5+5;int n,pn,sn;int p[maxn],x[maxn];char S[maxn];int calc(int l,int r,int pos){    return min(abs(pos-l),abs(pos-r))+abs(r-l);}bool check(int temp){    int pre=-1,pos=-1;    for(int i=0;i<pn;i++){        while((pos<sn-1)&&(calc(x[pre+1],x[pos+1],p[i])<=temp)) ++pos;        pre=pos;    }    return pos==sn-1;}int main(){   scanf("%d%s",&n,S);    pn=0,sn=0;    for(int i=0;i<n;i++){        if(S[i]=='P') p[pn++]=i;        if(S[i]=='*') x[sn++]=i;    }    int l=0,r=2*n;    while(l<r){        int mid=(l+r)>>1;        if(check(mid)) r=mid;        else l=mid+1;    }    printf("%d\n",r);}

23
**P………**P
8// 答案
0 0 4 //cal函数的参数打印
0 1 4
0 2 4
0 3 4
0 5 4
0 6 4
0 16 4

5

16 16 20
16 17 20
16 18 20
16 19 20
16 21 20
16 22 20

11 //pos

11%%11

另一组样例

10
.*PP.*P.
()8
1 1 3
1 2 3
1 6 3
1 9 3

2

9 9 4

3

3

3%%3
()7
1 1 3
1 2 3
1 6 3
1 9 3

2

9 9 4

3

3

3%%3
7

打印程序#include<bits/stdc++.h>using namespace std;const int maxn=1e5+5;int n,pn,sn;int p[maxn],x[maxn];char S[maxn];int calc(int l,int r,int pos){      cout<<l<<" "<<r<<" "<<pos<<endl;    return min(abs(pos-l),abs(pos-r))+abs(r-l);}bool check(int temp){    int pre=-1,pos=-1;    for(int i=0;i<pn;i++){        while((pos<sn-1)&&(calc(x[pre+1],x[pos+1],p[i])<=temp)) ++pos;        pre=pos;        cout<<"##"<<pos<<endl;    }    cout<<pos<<"%%"<<sn-1<<endl;    return pos==sn-1;}int main(){   scanf("%d%s",&n,S);    pn=0,sn=0;    for(int i=0;i<n;i++){        if(S[i]=='P') p[pn++]=i;        if(S[i]=='*') x[sn++]=i;    }    int l=7,r=10;    while(l<r){        int mid=(l+r)>>1;        cout<<"()"<<mid<<endl;        if(check(mid)) r=mid;        else l=mid+1;    }    printf("%d\n",r);}
原创粉丝点击