Problem A

题目大意

给定两个字符串,要求构造出一个最长的一个串满足:这个串是其中一个串的字序列并且不是另一个串的子序列.输出长度.\((len \leq 10^5)\)

题解

千万年死在读题上

我做题的时候:哇!这不是一道SB题嘛?

2mins敲完,提交Wrong answer

我去,好像看错题了。。我说怎么这道题这么二。。。

我重新看了眼题。。

那这题不更SB了吗??????

一边怀疑自己一边提交了上去,结果Accepted了。。

我去,判个字符串是否相等,再输出长度最大值就可以了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
char s1[maxn],s2[maxn];
int main(){
scanf("%s%s",s1+1,s2+1);
int len1 = strlen(s1+1);
int len2 = strlen(s2+1);
if(!strcmp(s1+1,s2+1)) puts("-1");
else printf("%d\n",max(len1,len2));
getchar();getchar();
return 0;
}

Problem B

题目大意

给定一个长为n的序列,判断是否能从这个序列中选出三个数使得这三个数可以组成一个三角形的三边长。\((n \leq 10^5)\)

题解

暴力枚举肯定不可行。

所以我们要有智商地枚举。

我们发现我们其实就是要在这里面选出三个数\(a,b,c\)满足

\(a+b > c ; a+c > b ; b+c > a\)

我们设\(a,b,c\)中最大值为\(a\),那么我们就发现\(a+b < c,a+c < b\)都一定成立

所以我们再选出两个小于等于\(a\)值满足\(b+c < a\)即可

所以我们直接对输入序列排序,顺序考虑\(a\)的取值

取第一个\(\leq a\)和第二个\(\leq a\)的值作为\(b,c\)判定即可

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
int a[maxn];
int main(){
int n;read(n);
for(int i=1;i<=n;++i) read(a[i]);
sort(a+1,a+n+1);
bool flag = false;
for(int i=3;i<=n;++i){
if(a[i-2] + a[i-1] > a[i]){
flag = true;
break;
}
}
puts(flag ? "YES" : "NO");
getchar();getchar();
return 0;
}

Problem C

题目大意

分别规定\(26\)个字母中每个字母所在的字符串长度不能超过某一值,给定一个长为\(n\)的字符串,将其划分成一些子串,使这个字符串满足上述要求。求:方案数\((mod \text{ } 10^9 + 7)\)、可行划分方案中的最长字串长度、最少划分成多少字串。\((ln \leq 10^5)\)

题解

又是一道字符串。。。

我们看到求方案数+取模就知道这一般不是一道数论题就是一道dp题

我们又看到了这数据范围就可以确定这是一个dp了

我们设\(f[i]\)表示成功划分了\(1~i\)的字符串的方案数,然后我们枚举\(j \in [0,i-1]\)转移即可。

第二问、第三问可以在算方案数的过程中直接记录或用类似过程计算

//没取模挂掉一次

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 1024;
const int mod = 1000000007;
int f[maxn],w[31],g[maxn];
char s[maxn];
inline int id(char ch){return ch - 'a' + 1;}
int main(){
memset(g,0x3f,sizeof g);
int n;read(n);
scanf("%s",s+1);
for(int i=1;i<=26;++i) read(w[i]);
f[0] = 1;g[0] = 0;
int ans = 1;
for(int i=1;i<=n;++i){
int lim = w[id(s[i]) ];
int cnt = 1,j=i-1;
while(cnt <= lim && j >= 0){
f[i] += f[j];if(f[i] >= mod) f[i] -= mod;
g[i] = min(g[i],g[j] + 1);
ans = max(ans,cnt);
++cnt;
lim = min(lim,w[id(s[j--])]);
}
}printf("%d\n%d\n%d\n",f[n],ans,g[n]);
getchar();getchar();
return 0;
}

Problem D

题目大意

给定n个词的含义相同或相反的共m个关系,关系具有传递性.每次给定关系的时候先判断此关系是否可以由前面的关系判断,如果不可以则添加此关系,否则判断此关系是否与推断出来的相符。最后询问q组词之间的关系。\((n,m,q \leq 10^5)\)

题解

一看这套路就知道是带权并查集。

每个节点维护父系指针和与父亲的关系。

我们把相反记为1,相同记为0.

每次判断亮点关系时只需要判断一下两点父亲是否相同

若父亲相同则可以推断两点的官司

若两点与父亲的关系均相同或均相反,则两点的关系为相同,否则为相反

至于关系的传递性嘛。。我们发现这个关系的传递性恰好是\(xor\)也就是异或

即\(num_{a->c} = num_{a->b}\text{ } xor \text{ }num_{b->c}\),其中\(num_{a->b}\)表示\(a,b\)的关系.

所以我们可以简单地完成路径压缩和查询。

竟然卡我的\(map!!!\)手写了颗\(Trie\)才过的...

#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
int fa[maxn],num[maxn];
inline int find(int x){
int f = x;while(f != fa[f]) f = fa[f];
int y = fa[x],z;
while(y != f){
z = fa[x];
while(z != f){
num[x] ^= num[z];
z = fa[z];
}fa[x] = f;
x = y;y = fa[x];
}return f;
}
const int maxnode = maxn*22 + 10;
int ch[maxnode][27],idx[maxnode],nodecnt;
inline void insert(int x){
char c;while(c = getchar(),c<'!');
int nw = 0;
while(c >= 'a' && c <= 'z'){
if(ch[nw][c - 'a'] == 0) ch[nw][c - 'a'] = ++nodecnt;
nw = ch[nw][c - 'a'];
c = getchar();
}idx[nw] = x;
}
inline int query(){
char c;while(c = getchar(),c<'!');
int nw = 0;
while(c >= 'a' && c <= 'z'){
nw = ch[nw][c - 'a'];
c = getchar();
}return idx[nw];
}
int main(){
int n,m,q;read(n);read(m);read(q);
for(int i=1;i<=n;++i){
insert(i);
fa[i] = i;
}
for(int i=1,c;i<=m;++i){
read(c);--c;
int x = query();
int y = query();
//printf("linking %d %d\n",x,y);
int fx = find(x);
int fy = find(y);
if(fx == fy){
if( (c == 0) == (num[x] == num[y]) ) puts("YES");
if( (c == 0) != (num[x] == num[y]) ) puts("NO");
}else{
fa[fx] = fy;
if(num[x]^num[y] == c) num[fx] = 0;
else num[fx] = 1;
puts("YES");
}
}
while(q--){
int x = query();
int y = query();
int fx = find(x);
int fy = find(y);
if(fx != fy) puts("3");
else printf("%d\n",(num[x] != num[y]) + 1);
}
getchar();getchar();
return 0;
}

Problen E

题目大意

给定一颗点有点权\((val_i \leq 10^6)\)的n个节点的树,定义两点距离为路径上点权异或和。求所有无序点对之间的距离之和。\((n \leq 10^5)\)

题解

因为这道题是对二进制数位进行操作

常规方法不好做的时候应该自然而然地想到对每个数位分别讨论。

我们发现:把每个数位拆开之后,所有的点权都变成了0/1

然后我们要统计的就是xor后为1的数对的个数

我们考虑树形dp

设\(f[i][j]\)表示以i为根的子树中到达点i时xor后得到j的节点数目.

即j是0或1

然后我们\(O(n)\)一遍可以算出所有点向上的贡献.

我们再\(dfs\)一遍算出所有点向下的贡献即可.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 100010;
bool w[maxn];
int a[maxn],f[maxn][2];
struct Edge{
int to,next;
}G[maxn<<1];
int head[maxn],cnt;
void add(int u,int v){
G[++cnt].to = v;
G[cnt].next = head[u];
head[u] = cnt;
}
inline void insert(int u,int v){
add(u,v);add(v,u);
}
#define v G[i].to
void dfs(int u,int fa){
f[u][0] = f[u][1] = 0;f[u][w[u]] = 1;
for(int i = head[u];i;i=G[i].next){
if(v == fa) continue;
dfs(v,u);
f[u][w[u]^0] += f[v][0];
f[u][w[u]^1] += f[v][1];
}return;
}ll num;
void dfs(int u,int fa,int zero,int one){
f[u][w[u]^0] += zero;f[u][w[u]^1] += one;
num += f[u][1];
int g[2];
for(int i=head[u];i;i=G[i].next){
if(v == fa) continue;
g[w[u]^1] = f[u][w[u]^1] - f[v][1];
g[w[u]^0] = f[u][w[u]^0] - f[v][0];
dfs(v,u,g[0],g[1]);
}
}
#undef v
int main(){
int n;read(n);
for(int i=1;i<=n;++i) read(a[i]);
for(int i=1,u,v;i<n;++i){
read(u);read(v);
insert(u,v);
}
#define v G[i].to
ll ans = 0;
for(int bit=1;bit<=30;++bit){
num = 0;
ll x = 0;
for(int i=1;i<=n;++i){
w[i] = (a[i] >> (bit-1)) & 1;
if(w[i] == 1) ++ x;
}
dfs(1,0);
dfs(1,0,0,0);
num = ((num-x)>>1) + x;
ans += num<<bit-1;
}
#undef v
printf("%lld\n",ans);
getchar();getchar();
return 0;
}

在vjudge上做完这些题后去codeforces开了Virtual participation,4分钟AC五道题,真爽!

Codeforces round 396(Div. 2) 题解的更多相关文章

  1. Codeforces Round #182 (Div. 1)题解【ABCD】

    Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...

  2. Codeforces Round #608 (Div. 2) 题解

    目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...

  3. Codeforces Round #525 (Div. 2)题解

    Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...

  4. Codeforces Round #528 (Div. 2)题解

    Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...

  5. Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F

    Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...

  6. Codeforces Round #677 (Div. 3) 题解

    Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...

  7. Codeforces Round #665 (Div. 2) 题解

    Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...

  8. Codeforces Round #160 (Div. 1) 题解【ABCD】

    Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...

  9. Codeforces Round #383 (Div. 2) 题解【ABCDE】

    Codeforces Round #383 (Div. 2) A. Arpa's hard exam and Mehrdad's naive cheat 题意 求1378^n mod 10 题解 直接 ...

随机推荐

  1. HTML元素定位

    一切皆为框 div.h1 或 p 元素常常被称为块级元素(block element).这意味着这些元素显示为一块内容,即"块框".与之相反,span 和 strong 等元素称为 ...

  2. JS——特效秀

    0.凛冬将至,用几款特效暖暖身    ①.tab图片切换: ②.索引图片切换:    ③.统计图: ④.滚动条分页:   1.Canvas跳动彩球时间动画特效  

  3. 具体解释TCP协议的服务特点以及连接建立与终止的过程(俗称三次握手四次挥手)

    转载请附本文的链接地址:http://blog.csdn.net/sahadev_/article/details/50780825 ,谢谢. tcp/ip技术经常会在我们面试的时候出现,非常多公司也 ...

  4. DataGrid绑定Dictionary问题

    问题] 在最近的项目中使用DataGrid的DataGridCheckBoxColumn绑定了后台TagModel类的IsSelected字段,数据源是TagModel类型的Dictionary,运行 ...

  5. Linux系统调用及用户编程接口(API)

    系统调用 所谓系统调用是指操作系统提供给用户程序调用的一组"特殊"接口,用户程序能够通过这组"特殊"接口来获得操作系统内核提供的服务.比如用户能够通过进程控制相 ...

  6. git merge的本质

    1 git merge [branch] 将[branch]这个分支merge到当前分支. 2 merge的本质 merge就是把branch上的提交合入当前分支的提交树,这两个分支上的所有提交的历史 ...

  7. js实现网页中的"运行代码"功能

    <!DOCTYPE html> <html> <head> <meta charset='utf8' /> <title>网页中的运行代码功 ...

  8. 宿舍更换的新淋浴喷头"水温vs旋钮角度"关系的研究(曲线)

    版权声明:我极少创造新知识,大部分情况下是个知识的二道贩子 https://blog.csdn.net/stereohomology/article/details/24478825 应该非常一目了然 ...

  9. Java for LeetCode 117 Populating Next Right Pointers in Each Node II

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  10. 设置sudo的过期时间

    默认sudo的过期时间过短,经常要输入密码 sudo visudo Defaults env_reset找到这行代码 后面加上timestamp_timeout参数,数值是分钟 ,timestamp_ ...