Codeforces round 396(Div. 2) 题解
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) 题解的更多相关文章
- Codeforces Round #182 (Div. 1)题解【ABCD】
Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...
- Codeforces Round #608 (Div. 2) 题解
目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...
- Codeforces Round #525 (Div. 2)题解
Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...
- Codeforces Round #528 (Div. 2)题解
Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...
- Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F
Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...
- Codeforces Round #677 (Div. 3) 题解
Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...
- Codeforces Round #665 (Div. 2) 题解
Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...
- Codeforces Round #160 (Div. 1) 题解【ABCD】
Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...
- 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 题解 直接 ...
随机推荐
- 怎么样自己动手写OS
虽然我现在并不是从事内核方向,却本着探索计算机本质的想法学习的内核,自从写完这个内核以后真的发现对很多东西的理解都更深一层,所以专研内核,对我现在的工作是很有帮助的.我个人强烈建议师弟师妹们尽早地啃一 ...
- ReactiveCocoa入门教程——第一部分【转载】
作为一个iOS开发者,你写的每一行代码几乎都是在响应某个事件,例如按钮的点击,收到网络消息,属性的变化(通过KVO)或者用户位置的变化(通过CoreLocation).但是这些事件都用不同的方式来处理 ...
- strpos与strstr之间的区别
string strstr(string haystack,string needle) 返回haystack中从第一 个needle开头到haystack末尾的字符串. 如果未找到needle 返回 ...
- Devexpress Spreadsheet 中文教程
http://blog.csdn.net/hotmee/article/details/50554381
- 【BZOJ1222】[HNOI2001]产品加工 DP
[BZOJ1222][HNOI2001]产品加工 Description 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同 ...
- Failed to load http://wantTOgo.com/get_sts_token/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fromHere.com' is therefore not allowed access.
Failed to load http://wantTOgo.com/get_sts_token/: No 'Access-Control-Allow-Origin' header is presen ...
- php.ini的几个关键配置
safe_mode = On safe_mode_gid = Off disable_functions = system,passthru,exec,shell_exec,popen,phpinfo ...
- php总结3——基本函数、流程控制中的循环
3.1 php基本函数(数学.日期.字符串) 数学函数:max mixed max(number $arg1,number $arg2,……) 求一组数据中的最大值 m ...
- 链表的C++实现
有的时候,处于内存中的数据并非连续的.那么这时候.我们就须要在数据结构中加入一个属性.这个属性会记录以下一个数据的地址.有了这个地址之后.全部的数据就像一条链子一样串起来了,那么这个地址属性就起到 ...
- JVM--内存区的划分
转自:http://www.jianshu.com/p/7ebbe102c1ae Java虚拟机在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域. java虚拟机运行时数据区 一. ...