A:Who is better?
题目链接:https://nanti.jisuanke.com/t/41383
题意:
类似于有N个石子,先手第一次不能拿完,每次后手只能拿 1 到 前一次拿的数量*2之间的数量,不能拿时则输
分析:
最近一直在刷博弈论的题,比赛的前一天晚上打的华东师范校赛第一题也刚好是道博弈题,说起来两者还是有点类似的地方
但是这题显然要难的多,好在我打完华东师范校赛的我又狠狠的把博弈论专题看了一遍,也很巧的看到了这两篇博客
https://blog.csdn.net/dgq8211/article/details/7602807
https://blog.csdn.net/iteye_6233/article/details/82396581
所以推导的时候就留意了斐波那契博弈...
有涉及到取模不用说exgcd往里丢就完事,找到前几个答案后再把规律扔到http://oeis.org/
很快发现当N为斐波那契数的时候先手是必输的
1 #include2 #include 3 #include 4 #include 5 #include
B:so easy
题目链接:https://nanti.jisuanke.com/t/41384
题意:
对于每次操作如果a是1则删除b,如果a是2则输出第一个大于等于b的数
分析:
我的水平真是对不起B题的题名
本来的想法是开个map——对于没有删除的数它对应的key值就为初始值0,对于删除的数它对应的初始值为1
然后对于key值为0的数直接输出即可,对于key值为1的数用二分找到第一个大于等于它的、且key值为0的数
然而map只是用来保存状态因此无法直接调用stl自带的二分,and手写的二分又各种bug,所以就很无奈的卡了一会
后来思索了一会想到题目的询问次数q<=1e6, 那么涉及到的数最多也只有1e6个,所以直接将所有读入的数保存+离散搞了一波
却很尴尬的WA了(这时候内心已经崩溃了)。 紧接着开始观察代码,因为比较长看得很晕,就索性认为是数据的储存出问题了
于是把所有数都输出来后,突然意识到二分只会对数组里的数进行操作,但是对于每个读入的数x,如果x已经被删除,那么我们
需要寻找的就是x的下一位数也就是x+1。
而仔细观察我们会发现每一次读入一个数XX的时候我们只要记录下XX+1,那么当下次我们要删除XX+1的时候,XX+2也会存在(读入的时候就会储存了)
于是我们查询第一个大于等于XX的时候要么答案为XX , 要么为XX+2(XX+1已被删除),这样就能保证题意
同理如果接来下我们要删除XX+2,那么在我们删除XX+2之前我们已将XX+3存入数组中,所以二分查找时就能找到XX+3
这道题还涉及到并查集的维护,这个操作也偏简单,就是维护XX的下一个空位(存在于数组中且未被删除)
1 #include2 #define numm ch - 48 3 using namespace std; 4 template 5 void read(T &res) 6 { 7 bool flag = false; 8 char ch; 9 while (!isdigit(ch = getchar())) 10 (ch == '-') && (flag = true); 11 for (res = numm; isdigit(ch = getchar()); res = (res << 1) + (res << 3) + numm) 12 ; 13 flag && (res = -res); 14 } 15 template 16 void Out(T x) 17 { 18 if (x < 0) 19 putchar('-'), x = -x; 20 if (x > 9) 21 Out(x / 10); 22 putchar(x % 10 + '0'); 23 } 24 const int N = 1e6 + 10; 25 int a[N][2]; 26 int ans[N * 3]; 27 int father[N * 3], cnt; 28 int find(int v) 29 { 30 return father[v] == v ? v : father[v] = find(father[v]); 31 } 32 int main() 33 { 34 int fuck, n, q, cot = 0, x; 35 read(n); 36 read(q); 37 for (int i = 1; i <= q; i++) 38 { 39 read(fuck), read(x); 40 ans[++cot] = x - 1; 41 ans[++cot] = x + 1; 42 ans[++cot] = x; 43 a[i][0] = fuck, a[i][1] = x; 44 } 45 sort(ans + 1, ans + 1 + cot); 46 int tot = unique(ans + 1, ans + 1 + cot) - ans - 1; 47 for (int i = 0; i <= tot + 1; i++) 48 father[i] = i; 49 for (int i = 1; i <= q; i++) 50 { 51 if (a[i][0] == 1) 52 { 53 int now = lower_bound(ans + 1, ans + 1 + tot, a[i][1]) - ans; 54 int u = find(now); 55 int v = find(now + 1); 56 father[u] = v; 57 } 58 else 59 { 60 int now = lower_bound(ans + 1, ans + 1 + tot, a[i][1]) - ans; 61 int u = find(now); 62 Out(ans[u]); 63 printf("\n"); 64 } 65 } 66 return 0; 67 }
赛后看了网上大佬的官方正解(unordered_map),再次为自己的菜感到自卑
老早前我就有在看关于hash表、hash函数的博客,虽然看懂了它的原理和储存方式,但却不知道具体代码实现的意义
今天特地问了一下大佬,这才知道unordered_map 其实和map差不多,简单讲一下区别:map和set差不多都有内置红黑树,就会自动按key值按字典序从小到大排序 而unordered_map 是采用了哈希函数,没有了排序功能,但是强大的点我们甚至可以用常数的时间进行查找的功能,最坏情况下也才是O(n) 而map的话因为排序了起步都是O(nlogn)
感觉收获还是蛮大的,下面贴下大佬的代码
1 #include2 using namespace std; 3 unordered_map<int,int> mp; 4 int n,m; 5 int find_pre(int x){ 6 if(!mp.count(x)) return x; 7 return mp[x]=find_pre(mp[x]); 8 } 9 int main(){ 10 scanf("%d %d",&n,&m); 11 int op,x; 12 while(m--){ 13 scanf("%d %d",&op,&x); 14 if(op==1) 15 mp[x]=find_pre(x+1); 16 else{ 17 x=find_pre(x); 18 if(x>n) printf("-1\n"); 19 else printf("%d\n",x); 20 } 21 } 22 return 0; 23 }
日后还是要深入学习一下
C. Buy Watermelon
题目链接:https://nanti.jisuanke.com/t/41385
题意:
将一个西瓜切成两半后再判断每半西瓜的重量是不是2的倍数
分析:
很无脑的签到题,直接判断N是不是偶数,再判断N是否>2即可
1 #include2 #include 3 #include 4 #define ll long long 5 #define inf 0x3f3f3f3f 6 using namespace std; 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 int w,flag=0; 11 cin>>w; 12 if(w>2&&w%2==0) 13 cout<<"YES\n"; 14 else 15 cout<<"NO\n"; 16 return 0; 17 }
D. Carneginon
题目链接:https://nanti.jisuanke.com/t/41386
题意:略
分析:
也是一道痕无脑的签到题,唯一恶心的点就是题目太长
1 #include2 #include 3 #include 4 #include 5 #include
E. XKC's basketball team
题目链接:https://nanti.jisuanke.com/t/41387
题意:
给你n个数字,寻找第i个数字后面比i大至少m且距离i最远的数字
分析:
这道题头都快给队友搞晕了
读完题后感觉问题相对来说还是偏简单,a的人也偏多,我就交给队友划个水转手去干B题了
然而等我 Accpet 完B题后已经过了很久然而队友还是没有给我答应,于是心态崩了 ,感觉自
己不止这一场而是最近几场都是一个人在战斗 , 所以最后也没有等时间结束就直接离场吃饭
去了。晚上去教室学习的时候看了下题解和大佬们的代码,基本上都和单调栈/队列 + 二分 、 线段树维护最大区间值 + 二分 离不开关系
然而队友隔了很久只给我发了一个双重for循环0优化的暴力,也是有点莫名其妙,感觉以后这种题还是得自己来,队友有点靠不住
暑期集训的线段树专题好像也有类似题型 , 斟酌了一会后提交一发过
1 #include2 #include 3 #include 4 #include 5 #include
G. Colorful String
题目链接:https://nanti.jisuanke.com/t/41389
题意:
给定一个字符串,将该字符串的所有回文串的不重复出现的字母贡献记为1,计算总贡献值
分析:
真是晕了。。。
读完题目感觉是自己能A的题,因为不久前刚粗略的学习了一手回文自动机,然而并没有什么锤子用
思考了快一个小时又想着用马拉车算法搞一波 ,but很快发现想法是错的,于是最后就很尴尬的把时
间浪费在这道题身上
果然自己对字符串的处理还是远远不够的。
上次找涛哥教AC自动机也不知道他什么时候有空教,感觉他最近也挺忙的。。。
我想主要还是要是要我多自学点吧,加油加油加油