D Tree Requests dfs+二分 D Pig and Palindromes -dp

D
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 then - 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 vihi. Let's consider the vertices in the subtree vi located at depthhi. 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 nm (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 vihi (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).

 

题解:把相同深度的点存入一个数组中,每个点都是当前这个点的在树中查找的时间  在询问的时候就按照深度在相应的 数组中找出 时间区间在某个区间内的点就ok了

#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <cstdio>
using namespace std;
#define mk make_pair
#define pub push_back
const int maxn=500005;
int num[maxn],depth[maxn],childmaxdepth[maxn];
int in[maxn],out[maxn],tim;
vector<int>G[maxn];
char str[maxn];
vector< pair<int,int>  >D[maxn];
void dfs(int cur,int de)
{
    int siz=G[cur].size();
    in[cur]=++tim;
    depth[cur]=childmaxdepth[cur]=de;
    if(D[de].size()<1){
        D[de].pub(mk(0,0));
    }
    int d=str[cur-1]-'a';
    D[de].pub(mk(in[cur],D[de].back().second^(1<<d)));
    for(int i=0; i<siz; i++)
        {
             int to=G[cur][i];
             dfs(to,de+1);
             childmaxdepth[cur]=max(childmaxdepth[cur],childmaxdepth[to]);

        }
    out[cur]=++tim;
}
int main()
{
     int n,m;
     while(scanf("%d%d",&n,&m)==2)
        {
            tim=0;
             for(int i=2; i <= n; i++)
             {
                 int d;
                 scanf("%d",&d);
                 G[d].push_back(i);
             }
             scanf("%s",str);
             dfs(1,1);
             for(int i=0; i<m; i++)
                {
                    int val,c;
                    scanf("%d%d",&val,&c);
                    if(childmaxdepth[val]<c||c<=depth[val])
                        {
                            puts("Yes");continue;
                        }
                    int L=lower_bound(D[c].begin(),D[c].end(),
                                        mk(in[val],-1))-D[c].begin();
                    int R=lower_bound(D[c].begin(),D[c].end(),
                                      mk(out[val],-1))-D[c].begin();
                    int t=D[c][L-1].second^D[c][R-1].second;
                    int ok=t-(t&(-t));
                    if(ok)puts("No");
                    else puts("Yes");
                }


        }
      return 0;
}
View Code

E

 给了一个矩阵 每个格子中有一个字符 然后要求从11 走到 nm 点 是一个回文串 只能从 向右或者向下走

我们枚举步数,然后 dp[x1][x2]可以得到 现在的点 (x1,y1), (x2,y2),然后我们再次使用利用滚动数组可以得到想要的  从之前的那些点得到

//向左向右 add(dp[cur][x1][x2],dp[cur^1][x1][x2]);

//向左向上 add(dp[cur][x1][x2],dp[cur^1][x1][x2+1]);

//向下向右 add(dp[cur][x1][x2],dp[cur^1][x1-1][x2]);

//向下向上 add(dp[cur][x1][x2],dp[cur^1][x1-1][x2+1]);

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=505;
long long dp[2][maxn][maxn];
char str[maxn][maxn];
const int mod=1000000007;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; i++)
        scanf("%s",str[i]);
    if(n+m<=3){
        printf("%d\n",str[0][0]==str[n-1][m-1]); return 0;
    }
    if(str[0][0]!=str[n-1][m-1]){
        printf("%d\n",0);return 0;
    }
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)dp[0][i][j]=0;
    dp[0][0][n-1]=1;
    int cur=0;
    for(int step=1; step<(n+m)/2;step++)
        {
              cur^=1;
              memset(dp[cur],0,sizeof(dp[cur]));
              for(int i=0; i < n&&i<=step; i++)
              for(int j=n-1; j>=0&&j>=i&&n-1-j<=step;j--)
                {
                  if( ( step - i )> ( m - 1 - ( step-( n - 1 - j ) ) ) )continue;
                  int x1=i,x2=j,y1=step-i,y2=m-1-(step-(n-1-j));
                  if(str[x1][y1]!=str[x2][y2])continue;
                  dp[cur][x1][x2]=dp[cur^1][x1][x2];
                  dp[cur][x1][x2]=( dp[cur][x1][x2] + dp[cur^1][x1][x2+1] )%mod;
                  if(x1>0)
                  {
                      dp[cur][x1][x2]=( dp[cur][x1][x2] + dp[cur^1][x1-1][x2] )%mod;
                      dp[cur][x1][x2]=( dp[cur][x1][x2] + dp[cur^1][x1-1][x2+1] )%mod;
                  }


                }
        }
        long long ans=0;
                for(int i=0; i<n; i++)
                   ans=(ans+dp[cur][i][i])%mod;
                if( (n+m)%2){

                    for(int i=0; i<n-1; i++)
                        ans=(ans+dp[cur][i][i+1])%mod;
                }
                printf("%I64d\n",ans);
    return 0;
}
View Code

 

posted @ 2015-08-22 09:54  来自大山深处的菜鸟  阅读(198)  评论(0编辑  收藏  举报