zoukankan      html  css  js  c++  java
  • 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
    ",str[0][0]==str[n-1][m-1]); return 0;
        }
        if(str[0][0]!=str[n-1][m-1]){
            printf("%d
    ",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
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    CSS知识总结一
    Html知识总结一
    转:B/S和C/S结构的区别
    转:理解本真的 REST 架构风格
    转载:简洁明了说明RESTful架构是什么
    名词理解
    转: 如何理解API,API 是如何工作的
    WEB的理解
    开关按钮的实现
    ssm学习之ssm框架详解
  • 原文地址:https://www.cnblogs.com/Opaser/p/4749650.html
Copyright © 2011-2022 走看看