Codeforces Round #316 (Div. 2)dfs序

B. Simple Game

One day Misha and Andrew were playing a very simple game. First, each player chooses an integer in the range from 1 to n. Let’s assume that Misha chose number m, and Andrew chose number a.

Then, by using a random generator they choose a random integer c in the range between 1 and n (any integer from 1 to n is chosen with the same probability), after which the winner is the player, whose number was closer to c. The boys agreed that if m and a are located on the same distance from c, Misha wins.

Andrew wants to win very much, so he asks you to help him. You know the number selected by Misha, and number n. You need to determine which value of a Andrew must choose, so that the probability of his victory is the highest possible.

More formally, you need to find such integer a (1 ≤ a ≤ n), that the probability that is maximal, where c is the equiprobably chosen integer from 1 to n (inclusive).

Input

The first line contains two integers n and m (1 ≤ m ≤ n ≤ 109) — the range of numbers in the game, and the number selected by Misha respectively.

Output

Print a single number — such value a, that probability that Andrew wins is the highest. If there are multiple such values, print the minimum of them.
Sample test(s)

Input

3 1

Output

2

Input

4 3

Output

2

Note

In the first sample test: Andrew wins if c is equal to 2 or 3. The probability that Andrew wins is 2 / 3. If Andrew chooses a = 3, the probability of winning will be 1 / 3. If a = 1, the probability of winning is 0.

In the second sample test: Andrew wins if c is equal to 1 and 2. The probability that Andrew wins is 1 / 2. For other choices of a the probability of winning is less.

思路:a肯定是选在区间长度大的那一段,并且紧挨着m的那个位置

#include<bits/stdc++.h>
using namespace std;
int N,M;
int main(){
    scanf("%d%d",&N,&M);
    if(N==1){
        printf("1\n");
        return 0;
    }
    if(M-1==N-M){
        printf("%d\n",M-1);
    } else if(M-1>N-M){
        printf("%d\n",M-1);
    } else {
        printf("%d\n",M+1);
    }
    return 0;
}

C. Replacement

Daniel has a string s, consisting of lowercase English letters and period signs (characters ‘.’). Let’s define the operation of replacement as the following sequence of steps: find a substring “..” (two consecutive periods) in string s, of all occurrences of the substring let’s choose the first one, and replace this substring with string “.”. In other words, during the replacement operation, the first two consecutive periods are replaced by one. If string s contains no two consecutive periods, then nothing happens.

Let’s define f(s) as the minimum number of operations of replacement to perform, so that the string does not have any two consecutive periods left.

You need to process m queries, the i-th results in that the character at position xi (1 ≤ xi ≤ n) of string s is assigned value ci. After each operation you have to calculate and output the value of f(s).

Help Daniel to process all queries.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 300 000) the length of the string and the number of queries.

The second line contains string s, consisting of n lowercase English letters and period signs.

The following m lines contain the descriptions of queries. The i-th line contains integer xi and ci (1 ≤ xi ≤ n, ci — a lowercas English letter or a period sign), describing the query of assigning symbol ci to position xi.

Output

Print m numbers, one per line, the i-th of these numbers must be equal to the value of f(s) after performing the i-th assignment.
Sample test(s)
Input

10 3
.b..bz….
1 h
3 c
9 f

Output

4
3
1

Input

4 4
.cc.
2 .
3 .
2 a
1 a

Output

1
3
1
1

Note

Note to the first sample test (replaced periods are enclosed in square brackets).

The original string is “.b..bz….”.

after the first query f(hb..bz....) = 4    ("hb[..]bz...."  →  "hb.bz[..].."  →  "hb.bz[..]."  →  "hb.bz[..]"  →  "hb.bz.")
after the second query f(hbс.bz....) = 3    ("hbс.bz[..].."  →  "hbс.bz[..]."  →  "hbс.bz[..]"  →  "hbс.bz.")
after the third query f(hbс.bz..f.) = 1    ("hbс.bz[..]f."  →  "hbс.bz.f.")

Note to the second sample test.

The original string is “.cc.”.

after the first query: f(..c.) = 1    ("[..]c."  →  ".c.")
after the second query: f(....) = 3    ("[..].."  →  "[..]."  →  "[..]"  →  ".")
after the third query: f(.a..) = 1    (".a[..]"  →  ".a.")
after the fourth query: f(aa..) = 1    ("aa[..]"  →  "aa.")

思路:对于每次修改,那只会影响.X.这三个,最多变化两次操作

#include<bits/stdc++.h>
using namespace std;
int N,M;
string s,c;
int x;
int main(){

    cin>>N>>M;
    cin>>s;
    int len=s.size();
    int ans=0,cnt=s[0]=='.'?1:0;
    for(int i=1;i<len;i++){
        if(s[i]=='.'){
            cnt++;
        }
        if(s[i]!='.'||i==len-1){
            ans+=(cnt>1?cnt-1:0);
            cnt=0;
        }
    }
    while(M--){
        cin>>x>>c;
        x--;
        if(c[0]=='.'){
            if(s[x]=='.'){
                printf("%d\n",ans);
            } else {
                ans+=(x>0&&s[x-1]=='.')+(x<len-1&&s[x+1]=='.');
                printf("%d\n",ans);
            }
        } else {
            if(s[x]!='.'){
                printf("%d\n",ans);
            } else {
                ans-=(x>0&&s[x-1]=='.')+(x<len-1&&s[x+1]=='.');
                printf("%d\n",ans);
            }
        }
        s[x]=c[0];
    }
    return 0;
}

D. Tree Requests

Roman planted a tree consisting of n vertices. Each vertex contains a lowercase English letter. Vertex 1 is the root of the tree, each of the n - 1 remaining vertices has a parent in the tree. Vertex is connected with its parent by an edge. The parent of vertex i is vertex pi, the parent index is always less than the index of the vertex (i.e., pi < i).

The depth of the vertex is the number of nodes on the path from the root to v along the edges. In particular, the depth of the root is equal to 1.

We say that vertex u is in the subtree of vertex v, if we can get from u to v, moving from the vertex to the parent. In particular, vertex v is in its subtree.

Roma gives you m queries, the i-th of which consists of two numbers vi, hi. Let’s consider the vertices in the subtree vi located at depth hi. Determine whether you can use the letters written at these vertices to make a string that is a palindrome. The letters that are written in the vertexes, can be rearranged in any order to make a palindrome, but all letters should be used.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 500 000) — the number of nodes in the tree and queries, respectively.

The following line contains n - 1 integers p2, p3, …, pn — the parents of vertices from the second to the n-th (1 ≤ pi < i).

The next line contains n lowercase English letters, the i-th of these letters is written on vertex i.

Next m lines describe the queries, the i-th line contains two numbers vi, hi (1 ≤ vi, hi ≤ n) — the vertex and the depth that appear in the i-th query.

Output

Print m lines. In the i-th line print “Yes” (without the quotes), if in the i-th query you can make a palindrome from the letters written on the vertices, otherwise print “No” (without the quotes).
Sample test(s)
Input

6 5
1 1 1 3 3
zacccd
1 1
3 3
4 1
6 1
1 2

Output

Yes
No
Yes
Yes
Yes

Note

String s is a palindrome if reads the same from left to right and from right to left. In particular, an empty string is a palindrome.

Clarification for the sample test.

In the first query there exists only a vertex 1 satisfying all the conditions, we can form a palindrome “z”.

In the second query vertices 5 and 6 satisfy condititions, they contain letters “с” and “d” respectively. It is impossible to form a palindrome of them.

In the third query there exist no vertices at depth 1 and in subtree of 4. We may form an empty palindrome.

In the fourth query there exist no vertices in subtree of 6 at depth 1. We may form an empty palindrome.

In the fifth query there vertices 2, 3 and 4 satisfying all conditions above, they contain letters “a”, “c” and “c”. We may form a palindrome “cac”.

思路:首先对每个点求一个dfs序,然后将它们存到对应的深度vector中,那么对于每个节点的孩子,他们在vector中是挨着的(因为dfs肯定是访问完这棵子树再去访问别的),所以可以用二分在查询时找到这个节点在这个深度下的区间。对于怎么判断回文串那,这个可以对每一个深度保存一个mask表示,每个元素是一个整数,用26位表示26个字母的出现次数的奇偶性,这样判断是不是回文串,只需要对上面求出的区间中的值异或一下判断是不是小于等于一位上面是1就行了

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=500010;
int N,M;
int dep[maxn];
char s[maxn];
vector<int> G[maxn];
vector<int> A[maxn];
vector<int> mask[maxn];
int w[maxn],fw[maxn],num[maxn];
int dfs_clock;

void dfs(int u,int fa,int depth){
    dep[u]=depth;
    w[u]=++dfs_clock;
    fw[dfs_clock]=u;
    A[depth].push_back(w[u]);
    mask[depth].push_back(mask[depth].back()^(1<<(s[u]-'a')));
    num[u]=1;
    int len=G[u].size();
    for(int i=0;i<len;i++){
        int v=G[u][i];
        if(v==fa)continue;
        dfs(v,u,depth+1);
        num[u]+=num[v];
    }
}
int cnt[30];
int main(){
    int u,v;
    scanf("%d%d",&N,&M);
    for(int i=0;i<=N;i++){
        G[i].clear();
        A[i].clear();
        mask[i].clear();
        num[i]=0;
    }
    dfs_clock=0;
    for(int i=2;i<=N;i++){
        scanf("%d",&u);
        G[u].push_back(i);
    }
    scanf("%s",s+1);
    for(int i=0;i<=N;i++){
        A[i].push_back(0);
        mask[i].push_back(0);
    }
    dfs(1,0,1);

    while(M--){

        scanf("%d%d",&u,&v);
        int l=w[u],r=w[u]+num[u]-1;
        int ll=lower_bound(A[v].begin(),A[v].end(),l)-A[v].begin();
        if(ll>=A[v].size()){
            printf("Yes\n");
            continue;
        }
        if(A[v][ll]<l)ll++;

        int rr=lower_bound(A[v].begin(),A[v].end(),r)-A[v].begin();
        if(A[v][rr]>r||rr==A[v].size())rr--;

        int x=(mask[v][rr]^mask[v][ll-1]);

        if(x-(x&(-x))==0){
            printf("Yes\n");
        } else {
            printf("No\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值