DAY16DAY 16DAY16
中考成绩出的前一个晚上,夜长梦多,不知道醒了多少次,每次都是梦到了中考成绩放榜前几分钟,然后就醒了,所以固然没睡好。再加上有人夜观天象(偷偷看题)说明日的题目很难,有点丧失做题欲望。
T1T1T1
wyl8899的TLEwyl8899的TLEwyl8899的TLE
Description
wyl8899今天也很刻苦的在做老师布置下来的题目!
这一天老师布置的题目是这样的:
给出两个仅含小写字母的字符串A和B,输出最大的k,使得A[1…k]是B的子串。
A和B的长度都不会超过50000。
很显然他并不知道正确的做法,但是他居然卡着时间过掉了老师给的数据!
你找到了他提交给老师的程序,经过测试你惊讶的发现,他的程序运行时间恰好是最终答案,单位是毫秒。
你现在找到了老师给的数据中的一笔,你决定至多修改A串中的一个字母,使得他的程序尽可能的慢。
现在,你能告诉我修改数据之后他的程序在这个测试点的运行时间么?(单位当然还是毫秒)
Input
两行,每行一个仅含小写字母的字符串,分别是A和B。
保证A和B的长度都不超过50000。
Output
你修改数据之后,wyl8899的程序在这个测试点的运行时间,单位是毫秒。
Sample Input
输入1:
adbc
aabbabd
输入2:
aab
aabcc
Sample Output
输出1:
3
输出2:
3
Data Constraint
保证A和B的长度都不超过50000。
Hint
数据是在Windows下生成的,测评环境是Linux。
由于换行符的差异,对于C/C++选手,请不要使用gets(s)读入一行字符,建议使用scanf("%s",s)的形式。
Pascal选手直接使用readln()读入一行即可,理论上readln()不会受到不同换行符的影响。
考场当然没什么话可说,直接上暴力,想过也许什么kmp之类的可以乱搞搞,可是那个next数组我是真心理解不了,所以直接交了暴力,结果竟然还有84分,然后听大佬说n2是可以过的,于是乎我尝试犯罪,加了一个O3,然后就过了。
#pragma GCC optimize(3,"Ofast","inline")
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 5e4 + 10;
int len,len1,len2,cnt,ans;;
char s1[N],s2[N];
int min(int a,int b) {return a < b ? a : b;}
int max(int a,int b) {return a > b ? a : b;}
int main()
{
scanf("%s\n%s",s1,s2);
len1 = strlen(s1),len2 = strlen(s2);
for (int i = 0; i < len2; i ++)
{
cnt = 0;
len = 0;
for (int j = 0; j < len1; j ++)
{
if (i + j > len2 - 1) break;
if (len + len1 - j <= ans) break;
if (s2[i + j] != s1[j] && !cnt) len ++,cnt ++; else
if (s2[i + j] == s1[j]) len ++; else break;
}
ans = max(ans,len);
if (ans == min(len1,len2)) break;
}
printf("%d",ans);
return 0;
}
T2T2T2
法法塔的奖励法法塔的奖励法法塔的奖励
Description
法法塔是很喜欢写程序的。所以冒着就算码农屌丝一辈子的风险也大无畏地写着程序。
码农们为了表彰法法塔的坚持与执着,决定给法法塔颁布奖励,为了体现码农的屌丝气质,奖励也将由法法塔自己做出选择!
所有的奖励被组织成了一棵树的形态,每个点都有一个权值。法法塔首先选择一个子树,然后选择从该子树内的一个叶子节点到该子树的根的一条路径,将路径上节点的权值依次排成一个序列,求得这个序列的最长不下降子序列长度,这个长度就是他能得到的奖品数目。要求该子树的根必须被选择。
接下来就是法法塔进行选择的时间了。尽可能多地得到奖品是自然的。那么法法塔到底能够得到多少奖品呢?这是个很纠结的问题,他决定交给你来解决。对于每个子树,他都希望你能求出他首先选择了这个子树后,他能得到的最多的奖品数目。
Input
第一行一个数n,描述树上节点的个数。
接下来一行n个数,描述树上每个点的父亲,点1为根,其父亲设为-1,其余每个点的父亲的标号都小于自己。
接下来一行n个数,表示树上每个点的权值。
Output
一行n个数,第i个数表示法法塔选择了以第i个节点为根的子树后,他可以获得的最多的奖品个数。
Sample Input
输入1:
2
-1 1
1 1
输入2:
6
-1 1 2 1 2 4
4 3 4 3 6 2
Sample Output
输出1:
2 1
输出2:
3 1 1 2 1 1
Data Constraint
n<=100000,每个数的权值都是1到n的正整数。
额,好像还是只会暴力,好吧,自己菜没办法,然后就打了一个时间复杂度古怪的暴力,从所有的叶子节点出发,更新一遍答案,第一次由于看漏了根节点必须选的条件,于是就爆零,然后改过之后,变成了二十分。不过听说还是有人用暴力过了,我为了学习一下新算法,学了一下线段树合并。线段树合并本来并不难,很容易理解。可是这道题,还是只能理解个一知半解。
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
struct Edge{
int to,next;
} f[N];
struct Node{
int l,r,mx;
} tr[N * 20];
int n,a[N],head[N],cnt = 0,ans[N],root[N],tot = 0;
int read()
{
int x = 0,w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') w = -1;ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}
return x * w;
}
int max(int a,int b) {return a > b ? a : b;}
void add(int u,int v)
{
f[++ cnt].to = v;
f[cnt].next = head[u];
head[u] = cnt;
}
int merge(int a,int b,int l,int r)
{
if (!(a * b)) return a + b;
if (l == r)
{
tr[a].mx = max(tr[a].mx,tr[b].mx);
return a;
}
int mid = (l + r) >> 1;
tr[a].l = merge(tr[a].l,tr[b].l,l,mid);
tr[a].r = merge(tr[a].r,tr[b].r,mid + 1,r);
tr[a].mx = max(tr[a].mx,tr[b].mx);
return a;
}
int query(int x,int l,int r,int a,int b)
{
if (!x) return 0;
if (l == a && r == b) return tr[x].mx;
int mid = (l + r) >> 1;
if (a > mid) return query(tr[x].r,mid + 1,r,a,b);
else if (b <= mid) return query(tr[x].l,l,mid,a,b);
else return max(query(tr[x].l,l,mid,a,mid),query(tr[x].r,mid + 1,r,mid + 1,b));
}
void change(int &x,int l,int r,int a,int b)
{
if (!x) x = ++ tot;
if (l == r)
{
tr[x].mx = max(tr[x].mx,b);
return;
}
int mid = (l + r) >> 1;
if (a <= mid) change(tr[x].l,l,mid,a,b); else change(tr[x].r,mid + 1,r,a,b);
tr[x].mx = max(tr[tr[x].l].mx,tr[tr[x].r].mx);
}
void solve(int x)
{
int j = 0;
for (int i = head[x]; i; i = f[i].next)
{
solve(f[i].to);
j = merge(j,root[f[i].to],1,n);
}
ans[x] = query(j,1,n,1,a[x]) + 1;
change(j,1,n,a[x],ans[x]);
root[x] = j;
}
int main()
{
n = read();
for (int i = 1,u; i <= n; i ++)
{
u = read();
if (~u) add(u,i);
}
for (int i = 1; i <= n; i ++) a[i] = read();
solve(1);
for (int i = 1; i <= n; i ++) printf("%d ",ans[i]);
return 0;
}
T3T3T3
wyl8899和法法塔的游戏wyl8899和法法塔的游戏wyl8899和法法塔的游戏
Description
法法塔和wyl8899都喜欢玩游戏。但是每次玩游戏法法塔都被wyl8899虐。
为了安慰可怜的法法塔,wyl8899决定大发慈悲,修改了一下游戏规则。
是这样的,这儿有一堆石子排成一列,每次wyl8899让hza选择一个区间进行游戏。游戏嘛,就是采用最普通的规则:两人轮流操作,每次选择一堆石子,取掉不为0的石子数,没法操作者失败。法法塔要做的是这样的:
我们现在定义一个区间的弱菜值:表示如果法法塔先取石子,而且法法塔第一步取的石子规定是最右边的那堆的话,为了必胜,第一步需要取的石子数。如果没法获胜的话,那么弱菜值就是-1。
法法塔要选择一个区间[l,r],使得r为wyl8899给定的某个数,l属于[a,b],a,b也是wyl8899给定的,要求这个区间的弱菜值是满足前面的条件中最大。请给出这个最大的弱菜值。
如果最大弱菜值不为-1,法法塔就会马上取走该区间最右端的石子堆最大弱菜值数量的石子。
Input
第一行一个正整数n,描述了石子的堆数,接下来一行n个数,描述每堆石子的数目。
接下来一行m,表示将进行要进行m次游戏,每次游戏由三个值刻画,r,a,b。r表示被选定的右端点,[a,b]表示选择的区间的左端点的范围
Output
对于每个询问输出最大的弱菜值。
Sample Input
输入1:
12
662 477 125 483 17 560 232 59 176 928 807 659
5
5 2 5
4 4 4
2 1 2
6 4 6
6 2 3
输入2:
7
230 883 456 1020 966 899 610
2
7 1 2
2 1 2
输入3:
11
392 808 14 71 393 79 11 74 713 232 142
5
8 3 8
9 5 9
3 1 1
8 2 8
7 4 6
Sample Output
输出1:
17
483
477
560
-1
输出2:
352
883
输出3:
74
713
-1
-1
-1
Data Constraint
n<=100000,m<=10000,每堆的石子数<=1000。
考场弃疗,考后才知道这道题是个结论题,所以只要做过类似题目的大佬都会做,and这道题时限给了3000ms,所以nm暴力可以过,结论是将每堆石子的个数异或一下,然后异或的值如果为零则答案为负一,否则就用右端点减去该异或的最小值便是答案。
#pragma GCC optimize(3,"Ofast","inline")
#include <cstdio>
using namespace std;
const int N = 1e5 + 10;
int n,v[N],q,r,a,b,s,mi = 2000;
int read()
{
int x = 0,w = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') w = -1;ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}
return x * w;
}
int min(int a,int b) {return a < b ? a : b;}
int main()
{
n = read();
for (int i = 1; i <= n; i ++) v[i] = read();
q = read();
while (q --)
{
r = read(),a = read(),b = read();
if (v[r] == 0) {printf("%d\n",-1); continue;}
if (r == b)
{
printf("%d\n",v[r]);
v[r] = 0;
continue;
}
s = 0,mi = 1000000;
for (int i = r - 1; i >= a; i --)
{
s ^= v[i];
if (i <= b) mi = min(mi,s);
}
if (mi > v[r] || v[r] - mi == 0) {printf("%d\n",-1); continue;} else printf("%d\n",v[r] - mi);
v[r] = mi;
}
return 0;
}
不过这套题其实并没有他们说的那么难。
唉中考果然还是没能屏蔽,初三下学期的成绩进步本来都已经给自己带来了极大的信心,结果还是没能在中考时画上完美的句号。。。。。。。