今天是暑训第一天,准备每天记录一下自己干了什么,督促自己不摸鱼
早上
早上找了点cf的题目复健一下。
cf732 div2 C. AquaMoon and Strange Sort
题目大意
给出一个长度为n的数组,每个位置一个ai值表示大小和一个方向值,方向值最开始都为R。
每次选取相邻的两个数调换位置,并且方向值取反(L变R,R变L)。
问能否让最后的数组不递减并且所有方向值都为R。
题目思路
其实我们很容易就会发现一个数移动偶数个格子那么他的方向值一定会变回原来的值。
题目要求数组不递减,所以我们肯定要做一个排序。
如果数组不出现重复数字,那么我们只要判断每个数到最终位置的距离是否为偶数。
出现重复数字的情况,就需要记录重复的数字在奇数位置的有多少个,偶数位置的有多少个,最后遍历数组判断一下
这题其实想了很久还是有点懵,最后看了别人的思路,才做出来的。
仔细思考了下自己的思路两种分类和距离为偶数一定不变的规律都想到了,但是在重复情况上并没有往找到的规律上面靠,所以一直没有一个完善的思路,思维题还是应该抓着规律不放的。
cf731 div3 E. Air Conditioners
题目大意
有个长度为n的数轴,还有k个空调,每个空调位于aj位置,并且温度为tj。
每个空调给到数轴上的温度为tj+|aj-i|。
最后求每个点在所有空调的作用下的最小值
题目思路
这题暴力解法是n*k。
题目的数据范围是3e5,所以考虑降低暴力的复杂度。
我们观察题目给的条件可以发现空调给自己在的位置的影响一定是tj,
并且他给周围的温度影响按距离增加。
我们给空调温度做个从小往大的排序。
我们从最小空调所在位置开始向左右更新值,因为向左右更新温度都是加一。
所以当更新点存在空调并且温度小于等于当前空调传输温度
或者当前位置温度小于或者等于当前空调传输温度时,就不用跟新了。
之后我们在按照这样的方法遍历每一个空调,更新最小值就好了。
这样我们每次枚举空调时就不用遍历整个数轴了。
我这样的写法最后的用了982ms,看了下别人的写法只用了200ms
大致思路就是每个空调都会向左和向右影响,
那么分两次做操作,第一次只考虑空调向右影响
第二次只考虑空调向左影响,最后的将向左和向右的值取个min就好了
这样复杂度就直接掉到n+k左右了,有点神奇。
下午
cf729 div2 B. Plus and Multiply
题目大意
有一个无限的集合,一开始只有1在里面。
我们规定当x在集合中时,那么x*a和x+b也要加入集合中。
给出n、a、b,问n是否能放入集合中
题目思路
根据题目条件,可以发现n=a^x+by这个式子是一定成立的。
那么把式子变化一下
(n-a^x)=by
(n-a^x)%b=0
最终我们可以把式子变成n%b=(a^x)%b
所以我们发现只要枚举a^x,然后判断上式是否成立。
还有一个特殊情况就是a==1,这个时候a^x的值都不会变,所以不需要在遍历了
emmm一道数学思维题想了好久都还是只有暴力的想法,果然还是一碰到数学就歇逼
想了好久还是看了题解才搞明白。还有就是这题的数据都要加上long long,没加一直tle不知道为什么
cf725 div3 F. Interesting Function
题目大意
给出l和r,我们每次个l+1,记录变化的数位并且累加,问当l==r时,总共有多少个数位变了
题目思路
这题一开始看感觉还挺吓人的,有种数位dp的感觉(虽然我不会)。
但手推了下1到10,1到100的值,再结合了下最后一个样例的值,
基本就可以打出1到10,1到100……1到1e9的表来了。
打完表之后,我们对于l和r的处理和前缀和的处理相同。
我们计算1到l和1到r的值再相减就是答案了
如果这里取1到l-1的话 答案还会多出一个l-1到l的值 所以不能这样选
cf717 div2 B. AGAGA XOOORRR
题目大意
给出一个长度为n的数组,可以选择相邻两个数做异或操作,删除这两个数,再将得到的值放入原位置。要求数组最后至少要有两个数,问能不能将数组中所有数变成相同的数
题目思路
对于这题我们从结果往前推,
假设最终数组长度为偶数,x、x、x、x、x、x。
我们对数组做操作
x、x、x、x、0
x、x、x、x
x、x、0
x、x
根据上面的演示,当长度为偶数时我们最短能将他减少到长度为2。
同上,最终数组长度为奇数时我们最短能减少到长度为3
我们根据上述结论就可以开始构造了。
当长度为偶数时,剩下两个值之间异或值为0,所以当整个数组异或和为0,那么答案就是YES
当长度为偶数时,我们考虑下面情况
x、x、x
x、0
x
我们最终可以将它化简成长度为1的数组,他的值其实就等于我们将所有数求异或和后的值。
所以这种情况下我们只需要查找前缀异或和和后缀异或和中同时等于所有数异或和的情况就好了
这题看的时候只觉得要用异或和,然后就啥想法没有了,盯了很久还是没思路。
最后看题解才知道咋思考。总结一下,这种数组删数的题,可以从奇偶两种情况去分析各自的特殊情况。还有就是正着推麻烦的时候, 尝试着从结果去推一些结论
刷了一天1500的题,感觉自己思维还是很局限,很多时候不知道咋破题,还是要多刷。
晚上看看字典树吧,重新认真学下
晚上
看了下字典树的封装,我的理解就是他是一个每个点有26的边的树,但是这个树是是动态开点的。需要这个边就开这个点。插入和查找都是o(n)的遍历比较,exist用于表示该字符串是否存在
洛谷 P2580 于是他错误的点名开始了
字典树的板子题,具体操作可以当作模板
int n,m;
char str[100];
int a[maxn][30];//字典树数组 第一维表示节点编号 第二位表示该边表示的字符
int tot=1;//节点数
int tag[maxn];//记录该点是否走过
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",str);
int len=strlen(str);
//插入操作
int u=1;//每次操作要从第一个结点开始遍历,不要用++tot
for(int j=0;j<len;j++)
{
int c=str[j]-'a';
if(!a[u][c])a[u][c]=++tot;
u=a[u][c];
}
tag[u]=1;
}
scanf("%d",&m);
while(m--)
{
scanf("%s",str);
int len=strlen(str)
//查询操作;
int u=1;
for(int i=0;i<len;i++)
{
int c=str[i]-'a';
u=a[u][c];
if(u==0)break;
}
if(tag[u]==1)printf("OK\n");
else if(tag[u]==0)printf("WRONG\n");
else printf("REPEAT\n");
if(tag[u]!=0)tag[u]++;
}
}