思维题
青烟绕指柔!
我不怕千万人阻挡,只怕自己投降。
展开
-
[KSN2021] Binary Land
题目链接:[KSN2021] Binary Land我们可以发现,如果一个数字最高位之后有一个0,那么是可以连向某个对应位置最高位为1的数字。然后这个不难想到可以对每一个二进制位建立虚点。我们发现如果这个虚点有作用,那么一定是某个数字最高位是这个,并且某个数字最高位之后某个0是这个。然后并查集维护连通性即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define原创 2021-11-29 16:35:11 · 790 阅读 · 0 评论 -
廊桥分配
题目链接:廊桥分配显然我们只需要对每一个飞机计算出降落在廊桥需要的廊桥个数。然后对于前后缀max进行枚举计算即可。具体的计算,其实我们就是去假设每个飞机来的时候会停在编号最小的廊桥,那么我们也就是停在廊桥的时候,通过编号计算出个数了。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;原创 2021-10-27 15:16:51 · 914 阅读 · 0 评论 -
制造游戏币
题目链接:制造游戏币这个其实就是有多条链的关系。所以我们肯定是提前先把物品拿到合法:也就是对于一条链来说,先拿 0 1 2 3 4 …个。然后每次就相当于可以拿一个后缀的所有物品。然后背包dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e5+10原创 2021-10-24 20:33:27 · 1954 阅读 · 0 评论 -
qko的爱情
题目链接:qko的爱情显然我们只需要没有人的点考虑。对于没有人的点,我们肯定是要使得整个子树向上移动,其实可以看出深度最大的点移动到这里。然后就可以用线段树维护区间最大的深度然后计算答案。我们要注意,计算的时候应该先递归子树,然后对当前没有人的点计算答案,因为对于两颗不同的子树,移动之后最大深度是会发生变化的。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#de原创 2021-07-05 14:46:57 · 238 阅读 · 0 评论 -
City Brain
题目链接:City Brain显然两条路径之间,相交的部分一定是一段连续的路径。所以我们可以枚举连续的路径,然后剩下4段不连续的路径。我们可以预处理两点之间的最短路,然后算出分别的和,然后三分即可。但是复杂度是 n * n * log 的。但是我们可以发现,对于枚举连续的相同长度的路径我们只需要知道4段不连续路径的最小值,然后复杂度就变成 n * n + n * log 了。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#in原创 2021-07-04 13:16:33 · 381 阅读 · 0 评论 -
佳佳的魔法药水
题目链接:佳佳的魔法药水看成一瓶药水要另一个药水的最短路,然后边权也是药水即可。因为要求方案数,所以我们更新的时候,保证作为边权的药水已经是最短的即可。然后要注意两瓶相同药水合成的情况。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1010;int n,原创 2021-06-28 13:01:31 · 247 阅读 · 0 评论 -
No Time to Dry P
题目链接:No Time to Dry P考虑对每个右端点维护左端点的答案。如果加进来的这个数字,上一次出现的位置到现在的位置都没有小于本身数字的,那么可从上一次涂的时候移动过来,所以 L 大于上一次的位置才需要重新涂,也就是区间 [上一次的位置+1 , i ]+1否则全体都需要重新涂,也就是总体+1所以离线fenwick或者在线主席树即可。因为主席树区间加比较麻烦,需要标记永久化,所以我们先差分一下。AC代码:#pragma GCC optimize("-Ofast","-funroll-原创 2021-06-27 17:29:25 · 212 阅读 · 0 评论 -
JABUKE
题目链接:JABUKE这种两维信息,不难想到维护一维,枚举一维。所以我们可以维护每个点左右最近的苹果树的位置,然后暴力枚举上下的位置更新即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=510;int n,m,q,dp1[N][N],dp2[N][N];原创 2021-06-26 11:26:40 · 175 阅读 · 0 评论 -
SZA-Template
题目链接:SZA-Template首先我们可以发现,答案一定是整个串的一个border。什么border是合法的呢?就是可以覆盖到所有点。我们用border树考虑,也就是每个节点相邻的最大差值要小于等于当前border长度。所以我们可以建树之后,从根节点一直向点n跑,直到存在一个合法的border,对于删除操作,我们使用链表维护即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h原创 2021-06-22 19:24:10 · 272 阅读 · 0 评论 -
[NOI2014] 动物园
题目链接:[NOI2014] 动物园维护一个border 树,然后对于每个点,继承父亲的答案,暴力向下跳即可。因为由于border树的性质,跳到的全是当前点的border为了方便向下跳,我们维护一个根节点到当前节点的节点栈AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const原创 2021-06-22 13:28:28 · 243 阅读 · 0 评论 -
Byfibonacci
题目链接:Byfibonacci这个题有一个trick,就是每个数字,不可能不由小于本身的最大两个fib组成。然后我们每次就枚举整个序列最大值是小于本身的第一个fib,还是第二个fib即可。但是我们要注意,次大的fib会计算重复。但是又最多用两次,所以可以容斥减掉。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing n原创 2021-06-20 20:57:09 · 391 阅读 · 0 评论 -
新年的饮食方案
题目链接:新年的饮食方案显然可以贪心,按照左端点排序后,对于每一天,我们每次去取结束时间最早的即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e6+10;int n,m,res,up,now;pair<int,int> a[N];pri原创 2021-03-20 00:05:12 · 120 阅读 · 0 评论 -
Simfonija
题目链接:Simfonija我们最后改变的k个数字,一定是改变排序后的两个端点区间的元素。所以我们可以枚举最后不会改变的 n-k 个数字,而且一定是连续的。所以也就是求这个连续区间的最小值,...原创 2021-03-18 14:59:49 · 110 阅读 · 0 评论 -
[清华集训2012]串珠子
题目链接:[清华集训2012]串珠子因为得到的是一个连通图,所以我们可以考虑用任意连边的方案数减去不连通的方案数。对于不连通的方案数,我们可以让一个子集连通,然后另一个子集随意连边。但是这样子集转移的时候是会计算重复的,所以我们可以考虑固定一个点,然后对于其他点来说就是与固定的点连通,然后不与固定的点连通。固定一个点也就是减去一个点,具体实现可以通过异或掉最低位来解决。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#includ原创 2021-03-17 09:48:47 · 213 阅读 · 0 评论 -
CCA的区间
题目链接:CCA的区间因为数字都不同,所以区间长度最多24,所以我们可以求出合法的子集区间。我们枚举一个需要的子集,然后对另一个取反后的集合求最大的子集即可,这个可以sosdp。因为可以反转区间,所以一定可以达到要求。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const in原创 2021-03-12 22:21:06 · 222 阅读 · 0 评论 -
没用的函数
题目链接:没用的函数我们可以枚举右端点,然后不同左端点的 gcdgcdgcd 一共只有 logloglog 段。然后我们暴力维护不同的左端点,然后区间求 maxmaxmax 即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e6+10;int n,mx[N原创 2021-03-10 14:54:01 · 137 阅读 · 0 评论 -
最小 OR 路径
题目链接:最小 OR 路径显然我们可以得到最高位,然后根据贪心是合法的。然后根据得到的高位又可以往低位看,然后看最高的必须合法的位。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e4+10,M=2e6+10;int n,m,s,t,res,ok,a[M],b原创 2021-03-08 20:21:25 · 172 阅读 · 0 评论 -
Kisik
题目链接:Kisik显然我们最后矩形的高度一定是物品的某一个高度。然后我们可以枚举高度然后选k个最小的宽度,排序后用堆维护k个最小值即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e6+10;int n,k,res=1e18,sum; priority_原创 2021-03-06 13:17:22 · 199 阅读 · 0 评论 -
「EZEC-6」分组
题目链接:「EZEC-6」分组我们可以发现一个 n*log 值域的简单做法,但是复杂度过高。我们可以发现,一个数字我们可以看成由最高位贡献,然后从低位枚举上去看是否合并。所以只需要二分最高位即可。复杂度就变成:O(nlog60+6060)AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;原创 2021-03-01 17:53:15 · 234 阅读 · 0 评论 -
[JOI 2021 Final] 雪玉
题目链接:[JOI 2021 Final] 雪玉我们可以注意到,对于一段相邻两个雪球组成的区间来说,这个区间只会对这两个雪球贡献。那么我们每次移动的时候,一定是小区间先被用完,那么我们可以维护移动过的区间,然后移出区间外在做贡献,贡献按照区间排序后就是一个区间加的问题了,可以前缀和。对于两个端点单独处理。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define i原创 2021-03-01 13:21:03 · 393 阅读 · 0 评论 -
Telephone G
题目链接:Telephone G因为此题DP的时候,转移成环,所以我们可以考虑最短路模型。我们对于这种绝对值距离,我们可以想到对相邻点建边权为1的边来解决。但是考虑种类问题。我们可以建立分层图,第0层为原图,第 1->k 层代表每种颜色,相邻边权为1,然后如果颜色相同则可以到达原图。最后因为边权只有0和1,01BFS即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h&g原创 2021-01-30 16:55:23 · 163 阅读 · 0 评论 -
No Time to Paint S
题目链接:No Time to Paint S显然答案可以分成一个前缀和一个后缀的和。所以我们如果可以预处理前后缀,那么问题就能解决了。假设对前缀考虑:如果当前的字符和前一次出现的位置之间的字符全部大于,那么从上一次的位置涂色过来即可,答案为上一次的次数。否则那么需要1次来涂色。对于求当前位置和上一次之间是否有小于的字符,做单调栈即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc原创 2021-01-29 20:34:14 · 339 阅读 · 0 评论 -
HDU - 6085
题目链接:HDU - 6085考虑每个数字 a % b == k,其实就是 ( a - k ) % b == 0,然后考虑使用bitset通过右移来维护。直接用bitset做位运算与。但是这样错过了一些数的因子,所以我们对于每个因子对因子的倍数来做贡献。我们枚举余数,从大到小维护一个bitset即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define i原创 2021-01-25 22:32:52 · 203 阅读 · 0 评论 -
「EZEC-5」魔法
题目链接:「EZEC-5」魔法不难发现一定是先做操作2。然后操作2一共最多执行log次。所以我们可以枚举操作2的次数。然后判断最小次数的操作1,二分即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e5+10;int n,A,B,s,a[N],res=1e原创 2021-01-23 23:40:51 · 244 阅读 · 0 评论 -
Poison AND^OR Affection
题目链接:Poison AND^OR Affection对于相同的右端点,我们可以发现当区间的左端点向左移动时,只有log个取值。因为每次要么不变,要么使得一个二进制位由0变成1。对于相同的贡献来说,右端点变大一定不会使得答案变劣,所以我们从最靠右的端点转移即可。如果发现不了,也可以利用区间max转移。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define in原创 2021-01-22 16:20:41 · 212 阅读 · 0 评论 -
Codeforces - Array Shrinking
题目链接:Array Shrinking显然最后的答案一定是多个连续的段缩成一个数,拼接而成。所以我们如果可以处理出每个段是否能缩成一个数就可以dp了。对于每个段,我们也可以区间dp。dp[i][j] 为 i ,j 这个区间能否缩成一个数,并且数的值。如果不能则为0转移枚举一个中间点即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int lo原创 2021-01-21 13:07:36 · 186 阅读 · 0 评论 -
Codeforces - AB-string
题目链接:AB-string考虑计算不合法的字符串。我们可以发现形式为:ABABBA______________BA用总方案减去即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=3e5+10;int n,res; char str[N];sign原创 2021-01-20 15:20:44 · 241 阅读 · 1 评论 -
完全平方数
题目链接:完全平方数首先可以想到二分。然后我们对于 2 的完全平方数来说,全部计算即可,3也同理。但是对于6来说,被计算了2次,所以需要减去。然后对于4来说,已经被2计算过了,跳过即可。其实我们不难发现,这就是莫比乌斯函数。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const i原创 2021-01-14 12:10:02 · 186 阅读 · 0 评论 -
Codeforces - Sum of Paths
题目链接:Codeforces - Sum of Paths不难发现,如果能维护每个点在所有路径上面的点数和,那么对于修改不难维护。所以考虑如何维护每个点的出现次数,我们枚举每个点,然后枚举当前点是路径上面第几个点即可。然后就是两种方案数的乘积,就是从任一点到这个点走 x 步的方案数 * 从这个点走 k-x 步出去的方案数。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>原创 2021-01-10 15:21:43 · 220 阅读 · 0 评论 -
CTOI10D2 - PIN
题目链接:CTOI10D2 - PIN我们枚举几个位置固定相等,然后其他位置不管,然后算出方案数。但是我们会发现计算重复了,比如3个位置一样会包含4个位置一样的。需要容斥掉。假设对于3个位置一样,因为对于某种3个位置的选择,会多计算一次4个位置的,然后有4种3个位置的,所以减去4倍的4个位置相同的方案数。对于2个位置一样,对于某种2个位置一样的选择,会有2种3个位置的,然后有6中2个位置的,然后3个位置的有4种,所以需要减去 2 * 6 / 4 种3个位置的方案数。其他同理。AC代码:#p原创 2021-01-06 15:28:30 · 114 阅读 · 0 评论 -
Codeforces - Little Elephant and Broken Sorting
题目链接:Codeforces - Little Elephant and Broken Sorting令 dp[i][j] 为 a[i] > a[j] 的概率。然后对于每次交换:交换位置为x,ydp[k][a] = dp[k][b] = ( dp[k][a] + dp[k][b] ) / 2dp[a][k] = dp[b][k] = 1.0 - dp[k][a]转移很显然。最后 dp[a][b] = dp[b][a] = 0.5AC代码:#pragma GCC optimize(原创 2021-01-06 10:58:45 · 162 阅读 · 0 评论 -
Subset
题目链接:Subset如果没用修改操作,直接sos dp即可。现在有修改,所以我们可以考虑值域分块。对于二进制前8位和后8位分开处理。令cnt[x][y] 为数字前8位为x,后8为的超集为y的个数。那么对于修改操作我们只需要枚举后8位即可。对于查询操作我们枚举前8位即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long long原创 2021-01-04 15:25:20 · 273 阅读 · 0 评论 -
AT3913 XOR Tree
题目链接:AT3913 XOR Tree每次操作一条链显然不可做,我们尝试利用异或转化为两点间的操作。我们于是可以把边权转化为点权,对于每个点权为相邻边的异或值。然后我们可以发现每次操作一条链只有两个端点会改变。然后对于显然变成两点间的操作,显然对于相同权值的点,贪心只用一次操作即可。否则那么点权都是不一样的,直接状压dp。因为权值很小。令dp[s]为当前的点权集合为s的答案,我们可以发现如果一个集合异或为0那么才是有解的。因为每次异或两个相同的数,整个集合的异或是不会改变的。所以我们单独对集合原创 2021-01-03 10:57:59 · 185 阅读 · 0 评论 -
Sweet Fruit Chocolate
题目链接:Sweet Fruit Chocolate考虑每个点的贡献即可,每个点如果选取,那么对所有祖先都有贡献,其实就是dep[x]*a[x],然后对于另外 n-1 个点有 2^(n-1)种选法。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e6+10,m原创 2020-12-21 11:44:37 · 179 阅读 · 0 评论 -
[PA2010]Riddle
题目链接:[PA2010]Riddle不难看出可以使用2-SAT去解决。对于每条边来说,相当于就是某个端点不取,另一个端点必须取。对于每个集合来说,我们就是如果这个点取,那么其他点不能取。但是不能暴力连边。我们可以如下建图:1 < 2 < 3 < 4 < 5 …1 > 2 > 3 > 4 > 5 …分别加上两排点,然后对于某个点取,往前后位置连边即可。因为数据比较大,边很多,所以用vector建图会TLE。pushback次数太多。AC代原创 2020-12-15 19:56:06 · 251 阅读 · 0 评论 -
Collecting stars
题目链接:Collecting stars首先答案一定是一段连续的区间。然后我们可以发现从 s 开始,我们如果只单向走一定是连续的。如果我们需要两边都到达的话,第一次走的一边一定是跳着走的。两种情况取max即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=原创 2020-12-10 18:05:16 · 283 阅读 · 0 评论 -
[POI2015]WIL-Wilcze doły
题目链接:[POI2015]WIL-Wilcze doły我们可以发现右端点向右移动的时候,左端点也是向右移动的。然后怎么判断当前区间是否合法呢? sum[r] - sum[l-1] - 区间长度为d的max。然后维护区间长度为d 的max,单调队列即可。AC代码:#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e6+10;int n,p,d,res,a[N],q[N]原创 2020-12-04 19:36:52 · 263 阅读 · 0 评论 -
Rencontre
题目链接:Rencontre首先对于树上,一个点到给定三个点的最短距离和为:(dis(x,y)+dis(y,z)+dis(x,z))/2然后对于线性期望,我们可以把这个拆开分别求和。E((dis(x,y)+dis(y,z)+dis(x,z))/2)=E(dis(x,y))/2+E(dis(y,z))/2+E(dis(x,z))/2然后就是求出两两之间的距离和。这个我们直接枚举每一条边的贡献即可。注意求出距离和之后变成期望应该除以两两之间的点个数之积。AC代码: #pragma GCC原创 2020-12-02 13:36:02 · 351 阅读 · 0 评论 -
Simple AniPop
题目链接:Simple AniPop不难看出可以区间dp。所以我们考虑后面拼接一段,断环成链。然后我们令 dp[i][j] 为区间 [ i , j ] 并且 i ,j 未被消掉的最大价值。然后枚举区间 [ i +1 , j -1 ]最后消掉的位置k做转移。最后不难看出答案就是 a[i] + dp[i][i+n] 的最大值。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>原创 2020-12-01 13:20:25 · 312 阅读 · 0 评论 -
Delete Prime
题目链接:Delete Prime对每个问题单独考虑。第二个问题就是第k个位置的值,那么我们对当前的n分解,直到当前分解出来大于k了,那么问题转化为第 i 轮被移出的第 j 个数的问题,直接在第 i 轮出去的前缀和上面二分。第一个问题就是 k 是第几个位置,同理每次对n分解,然后求出某次大于k了,那么就是求出数字是第 i 轮,第几个出去的,前缀和预处理即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<原创 2020-11-28 00:22:35 · 593 阅读 · 0 评论