Codeforces Round #316 (Div. 2)

A - Elections

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,num[105],a[105][105];
 4 int main()
 5 {
 6     scanf("%d%d",&n,&m);
 7     for(int i=1;i<=m;i++)
 8     {
 9         int item=1;
10         for(int j=1;j<=n;j++)
11         {
12             scanf("%d",&a[i][j]);
13             if(a[i][item]<a[i][j]) item=j;
14         }
15         num[item]++;
16     }
17     int item=1;
18     for(int i=1;i<=n;i++) if(num[i]>num[item]) item=i;
19     printf("%d\n",item);
20     return 0;
21 }

B - Simple Game

没注意输出最小的WA了一次。。。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n,a; scanf("%d%d",&n,&a);
 6     if(n==1)
 7     {
 8         puts("1");
 9         return 0;
10     }
11     else if(a==n)
12     {
13         printf("%d\n",a-1);
14         return 0;
15     }
16     else if(a==1)
17     {
18         printf("%d\n",a+1);
19         return 0;
20     }
21     int ans1=a-1,ans2=a+1;
22     printf("%d\n",ans1-1>=n-ans2 ? ans1:ans2);
23     return 0;
24 }

C - Replacement

题目大意:给你一个字符串,每次操作将两个相邻的点变成一个。 现在有m个操作,每个操作有一个 pos,一个c

是将pos位的字符变成c,问你这样需要几次操作。

思路:我们要知道一个串需要几次操作只需要知道这个串有多少个点 ,有多少段点,如果有m个点,有n段点,那么需要的操作数为m-n,然后改变字符的时候分类讨论一下就好啦。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=3e5+5;
 4 char s[N];
 5 int n,m,num,cnt;
 6 int main()
 7 {
 8     scanf("%d%d",&n,&m);
 9     scanf("%s",s+1);
10     for(int i=1;i<=n;i++)
11     {
12         if(s[i-1]!=‘.‘ && s[i]==‘.‘) cnt++;
13         if(s[i]==‘.‘) num++;
14     }
15     while(m--)
16     {
17         int pos; char ss[3];
18         scanf("%d%s",&pos,ss);
19         if(ss[0]==‘.‘)
20         {
21             if(s[pos]!=‘.‘)
22             {
23                 num++;
24                 if(s[pos-1]==‘.‘ && s[pos+1]==‘.‘) cnt--;
25                 else if(s[pos-1]!=‘.‘ && s[pos+1]!=‘.‘) cnt++;
26             }
27             s[pos]=ss[0];
28         }
29         else
30         {
31             if(s[pos]==‘.‘)
32             {
33                 num--;
34                 if(s[pos-1]==‘.‘ && s[pos+1]==‘.‘) cnt++;
35                 else if(s[pos-1]!=‘.‘ && s[pos+1]!=‘.‘) cnt--;
36             }
37             s[pos]=ss[0];
38         }
39         //printf("%d %d\n",num,cnt);
40         printf("%d\n",num-cnt);
41     }
42     return 0;
43 }

D - Tree Requests

题目大意:给你一棵树,每个节点对应一个字符,有m个询问,每个询问里边有一个v,一个h,v表示一个节点,h表示深度

问你在以v为根的子树中所有深度为h的点对应的字符能不能构成回文串。

在线:先对树进行dfs,过程中用dfs序找出每个节点的子树区间,将每个节点的dfs序放入对应的f[ i ][ j ]中,f[ i ][ j ]表示深度为i,对应字符为j+‘a‘。

然后对于每次询问,我们在f[ i ][ h ] (0<=i<26) 中二分找出l[v]-r[v]之间有多少个数,记录有多少个是奇数。

如果奇数的个数>=1 则NO 否则 YES。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=5e5+5;
 4 vector<int> f[N][26];
 5 struct edge
 6 {
 7     int to,nx;
 8 }e[N];
 9 int l[N],r[N],n,m,dfn,head[N],tot;
10 char s[N];
11 void add(int f,int t)
12 {
13     e[tot].to=t; e[tot].nx=head[f];
14     head[f]=tot++;
15 }
16 void dfs(int v,int deep)
17 {
18     l[v]=++dfn;
19     f[deep][s[v]-‘a‘].push_back(dfn);
20     for(int i=head[v];~i;i=e[i].nx)
21     {
22         int u=e[i].to;
23         dfs(u,deep+1);
24     }
25     r[v]=dfn;
26 }
27 int main()
28 {
29     memset(head,-1,sizeof(head));
30     scanf("%d%d",&n,&m);
31     for(int i=2;i<=n;i++)
32     {
33         int fa; scanf("%d",&fa);
34         add(fa,i);
35     }
36     scanf("%s",s+1);
37     dfs(1,1);
38     while(m--)
39     {
40         int v,h,cnt=0,sum=0; scanf("%d%d",&v,&h);
41         for(int i=0;i<26;i++)
42         {
43             int pos1=lower_bound(f[h][i].begin(),f[h][i].end(),l[v])-f[h][i].begin();
44             int pos2=lower_bound(f[h][i].begin(),f[h][i].end(),r[v]+1)-f[h][i].begin();
45             if((pos2-pos1)&1) cnt++;
46             if(cnt>1) break;
47         }
48         if(cnt>1) puts("No");
49         else puts("Yes");
50     }
51     return 0;
52 }

离线:对树进行dfs,将询问按深度分层,点按深度分成再按字符分类。然后用树状数组维护节点个数。

 1 #include<bits/stdc++.h>
 2 #define pii pair<int,int>
 3 #define fi first
 4 #define se second
 5 #define mk make_pair
 6 using namespace std;
 7 const int N=5e5+5;
 8 int n,m,dfn,l[N],r[N],up,ans[N],head[N],tot;
 9 char s[N];
10 vector<pii > Q[N];
11 vector<int> D[26][N];
12 struct BIT
13 {
14     int a[N];
15     void modify(int x,int v)
16     {
17         for(int i=x;i<=n;i+=i&-i) a[i]+=v;
18     }
19     int query(int x)
20     {
21         int ans=0;
22         for(int i=x;i>0;i-=i&-i) ans+=a[i];
23         return ans;
24     }
25 }bit;
26 struct edge
27 {
28     int to,nx;
29 }e[N];
30 void add(int f,int t)
31 {
32     e[tot].to=t; e[tot].nx=head[f];
33     head[f]=tot++;
34 }
35 void dfs(int v,int deep)
36 {
37     up=max(up,deep); l[v]=++dfn;
38     D[s[v]-‘a‘][deep].push_back(dfn);
39     for(int i=head[v];~i;i=e[i].nx) dfs(e[i].to,deep+1);
40     r[v]=dfn;
41 }
42 int main()
43 {
44     memset(head,-1,sizeof(head));
45     scanf("%d%d",&n,&m);
46     for(int i=2;i<=n;i++)
47     {
48         int fa; scanf("%d",&fa);
49         add(fa,i);
50     }
51     scanf("%s",s+1);
52     dfs(1,1);
53     for(int i=1;i<=m;i++)
54     {
55         int v,h; scanf("%d%d",&v,&h);
56         Q[h].push_back(mk(v,i));
57     }
58     for(int i=1;i<=up;i++)
59     {
60         for(int k=0;k<26;k++)
61         {
62             for(int j:D[k][i]) bit.modify(j,1);
63             for(pii j:Q[i])
64             {
65                 int cur=bit.query(r[j.fi])-bit.query(l[j.fi]-1);
66                 if(cur&1) ans[j.se]++;
67
68             }
69             for(int j:D[k][i]) bit.modify(j,-1);
70         }
71     }
72     for(int i=1;i<=m;i++) printf("%s\n",ans[i]<=1 ? "Yes":"No");
73     return 0;
74 }

E - Pig and Palindromes

题目大意:给你一个n*m的图(1<=n,m<=500) ,图由字符构成,现在你在(1,1)的位置,想走到(n,m)的位置,问你有多少种走法使路径构成回文串。

思路:动态规划题,其实题目相当于两个人分别从(1,1),(n,m)开始走,且只能走向字符相同得我位置,我们可以用dp[cnt][x1][y1][x2][y2]表示第cnt步的时候,第一个点在(x1,y1),第二个点在(x2,y2)时的方案数。但是很明显空间开不下,我们可以用滚动数组来进行优化,这样就变成了dp[2][x1][y1][x2][y2]。还是过大,其实如果我们知道了步数,知道了x的坐标就能推出y的坐标,最后变成了dp[2][x1][x2]。    状态转移方程为:

dp[cnt][x1][y1][x2][y2]+=dp[cnt-1][x1-1][y1][x2+1][y2]

dp[cnt][x1][y1][x2][y2]+=dp[cnt-1][x1-1][y1][x2][y2+1]

dp[cnt][x1][y1][x2][y2]+=dp[cnt-1][x1][y1-1][x2+1][y2]

dp[cnt][x1][y1][x2][y2]+=dp[cnt-1][x1][y1-1][x2][y2+1]

最后路径长度为奇数偶数的时候分类一下就好啦。

#include<bits/stdc++.h>
using namespace std;
const int N=505;
const int mod=1e9+7;
char s[N][N];
int n,m,dp[2][N][N];
inline void MOD(int &x){if(x>=mod) x-=mod;}
int solve()
{
    if(s[1][1]!=s[n][m]) return 0;
    dp[1][1][m]=1; int c=1,up=(n+m)>>1,ans=0;
    for(int k=1;k<up;k++)
    {
        c^=1;
        for(int i=1;i<=m;i++)
        {
            for(int j=i;j<=m;j++)
            {
                dp[c][i][j]=0;
                int x1=i,y1=1+(k-(i-1));
                int x2=j,y2=n-(k-(m-j));
                if(y1<1 || y2>n || y1>n || y2<1 || y1>y2) continue;
                if(s[y1][x1]!=s[y2][x2]) continue;

                if(x1>1 && x2<m) dp[c][i][j]+=dp[c^1][i-1][j+1],MOD(dp[c][i][j]);
                if(x1>1 && y2<n) dp[c][i][j]+=dp[c^1][i-1][j],MOD(dp[c][i][j]);

                if(y1>1 && x2<m) dp[c][i][j]+=dp[c^1][i][j+1],MOD(dp[c][i][j]);
                if(y1>1 && y2<n) dp[c][i][j]+=dp[c^1][i][j],MOD(dp[c][i][j]);
            }
        }
    }
    int sum=n+m;
    for(int i=1;i<=m;i++)
    {
        for(int j=i;j<=m;j++)
        {
            if(!dp[c][i][j]) continue;
            int x1=i,y1=1+(up-(i-1));
            int x2=j,y2=n-(up-(m-j));
            ans+=dp[c][i][j]; MOD(ans);
            if(!(sum&1) && i!=j) ans+=dp[c][i][j]; MOD(ans);
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    int ans=solve();
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/CJLHY/p/8228436.html

时间: 2024-10-02 02:10:04

Codeforces Round #316 (Div. 2)的相关文章

Codeforces Round #316 (Div. 2) B. Simple Game

思路:把n分成[1,n/2],[n/2+1,n],假设m在左区间.a=m+1,假设m在右区间,a=m-1.可是我居然忘了处理1,1这个特殊数据.被人hack了. 总结:下次一定要注意了,提交前一定要看下边界数据,不要急着交. 题目链接:http://codeforces.com/problemset/problem/570/B <pre name="code" class="cpp">#include<bits/stdc++.h> using

Codeforces Round #316 (Div. 2) C. Replacement

题意:给定一个字符串,里面有各种小写字母和' . ' ,无论是什么字母,都是一样的,假设遇到' . . ' ,就要合并成一个' .',有m个询问,每次都在字符串某个位置上将原来的字符改成题目给的字符,问每次须要多少次合并次数.才使字符串没有' .. ' 思路:最原始的想法,就是对于每一次询问,都遍历整个字符串.这样时间复杂度o(n*m),就高达10^10方,非常明显会tle. 换下思路,事实上每次询问所改变的字符都会保留到下一次.也就是下一次的次数就会受到上一次的影响,那么我仅仅要就算出第一次的

Codeforces Round #316 (Div. 2) D计算在一棵子树内某高度的节点

题:https://codeforces.com/contest/570/problem/D 题意:给定一个以11为根的n个节点的树,每个点上有一个字母(a~z),每个点的深度定义为该节点到11号节点路径上的点数.每次询问a,ba,b查询以aa为根的子树内深度为bb的节点上的字母重新排列之后是否能构成回文串.分析:很明显是个树上启发式合并.显然,只要深度为bb结点的所有颜色中,至多有一种的数量为奇数就可以构成回文串了. #include<bits/stdc++.h> using namespa

Codeforces Round #316 (Div. 2) A

Description The country of Byalechinsk is running elections involving n candidates. The country consists of m cities. We know how many people in each city voted for each candidate. The electoral system in the country is pretty unusual. At the first s

Codeforces Round #316 (Div. 2) D Tree Requests

官方题解是离线询问,dfs树形转线性,然后二分找区间. 还有一种比较好的做法是直接dfs,将当前访问这个结点u相关的询问之前的状态存起来,然后访问完以后利用异或开关性,得到这颗子树上的答案. 代码是学习别人的http://blog.csdn.net/squee_spoon/article/details/47666667 当时做的时候想得是树形转线性,觉得dfs会暴栈,想用bfs,之前又没写过,于是愣了一个钟头. #include<bits/stdc++.h> using namespace

2017-4-30-Train:Codeforces Round #316 (Div. 2)

A. Elections(模拟) The country of Byalechinsk is running elections involving n candidates. The country consists of m cities. We know how many people in each city voted for each candidate. The electoral system in the country is pretty unusual. At the fi

Codeforces Round #316 (Div. 2)E. Pig and Palindromes DP

E. Pig and Palindromes Peppa the Pig was walking and walked into the forest. What a strange coincidence! The forest has the shape of a rectangle, consisting of n rows and m columns. We enumerate the rows of the rectangle from top to bottom with numbe

Codeforces Round #316 (Div. 2)C. Replacement(模拟)

传送门 Description 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 st

570D Codeforces Round #316 (Div. 2) D(dfs序,时间戳,二分

题目:一棵树上每个节点有个字符值,询问每个节点的深度为h的子节点的字符是否能组成一个回文串. 思路:首先是奇妙的dfs序和时间戳,通过记录每个节点的dfs进出时间,可以发现某个节点的子节点的进出时间均在该节点的进出时间范围内(这是很直观的dfs的性质),这样可以把树形结构转变为线性结构,方便进行各种处理.dfs一遍处理时间戳,每个节点的深度,并记录每个深度的节点都有哪些,此时每个深度的节点就是排好序的.然后对于一个询问,可以利用二分查找确定子节点在该层的哪一段.对于每一层,预先处理每个字符的前缀

Codeforces Round #316 (Div. 2) D. Tree Requests 树 离线在线 算法

D. Tree Requests 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