摘要:
考虑将武器(a,b)看成一条无向边,那么对于一个连通块1.当没有环,即是一棵树,那么任选一个点作为根,每条边只选儿子节点即可,显然根要选编号最大的2.当有环,任选一个环作为根,其余环上的某一条边拆掉使得变成基环树,树边选择儿子,环边按某种顺序选择即可那么题目相当于要求维护每一个树连通块的最小的最大编 阅读全文
摘要:
容易发现幸运数字只有1024个,暴力标记倍数还是会tle的 容斥,即从中任选i个的lcm,复杂度为$o(2^1024)$ 剪枝一:当答案超过1024就不用算了 剪枝二:当某个数是另一个数的倍数时就删掉 (另外求lcm可能会爆long long,由于爆了long long一定不合法,因此可以用除法来判 阅读全文
摘要:
由于价格是单调递增的,因此可以直接建立Si条边,流量和价格依次为给定的函数即可(如果价格不递增,可以考虑动态加边等操作) 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1005 4 struct ji{ 5 int nex, 阅读全文
摘要:
先考虑选出k个后答案最小会是多少,容易发现其实就是所有的gcd(就是$ax+by=gcd(a,b)$的推广)然后相当于要最大化gcd,反过来可以将所有数的约数都打上+1标记,+1标记不少于k个且最大的数就是答案,由于值域较大,需要用map来维护 1 #include<bits/stdc++.h> 2 阅读全文
摘要:
第i次购物的花费是i元,那么意味着可以理解为消费要加上次数,因此预处理抽出i张牌后,抽出剩余n-i张牌的期望次数,设g[i]表示这个期望,那么有方程$g[i]=((n-i)*g[i+1]+i*g[i])/n+1$,化简得到$g[i]=g[i+1]+n/(n-i)$然后即可求出f[i]表示抽出i张牌后 阅读全文
摘要:
再随机生成一个n*1的矩阵D,若$A*B=C$,则显然有$A*B*D=C*D$,根据结合律,又有$A*(B*D)=C*D$由于(n*n)*(n*1)的复杂度是$o(n^2)$的,因此暴力乘法即可(程序的做法是判断乘起来的矩阵所有数字之和与C是否相同,即求$a[i][k]*b[k][j]$,对a的每一 阅读全文
摘要:
考虑建立一棵线段树,维护:1.左端点的连续1和;2.右端点的连续1和;3.最长1的连续子序列;4.1的个数;5.将0和1交换后上面的四项;6.懒标记具体实现中,需要注意细节,可以看代码(比较短) 1 #include<bits/stdc++.h> 2 using namespace std; 3 # 阅读全文
摘要:
二分枚举答案,假设是ans,考虑判定答案从前往后计算,算出每一个将军与第一个将军最少和最多有多少个相同的奖牌,贪心转移即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[20005]; 4 bool pd(int k){ 5 i 阅读全文
摘要:
对于这n个函数,构成了$n(n-1)/2$个交点,对交点离散后,相邻两个交点间函数的编号构成了一个排列,而每一个排列第i个数所构成的段数就是第i层的段数不妨设初始在-oo处这个排列是1,2,……,n,那么每经过一个交点可以看成是交换两个函数的编号,如果把先小后大看成逆序对,那么相当于是一个不断消除逆 阅读全文
摘要:
很有趣的一道题目,如何让一个程序输出自身如果用字符串s表示程序,那么意味着可以通过s来输出sprintf是一个可以利用的函数,相当于要求printf(s,s)输出的就是s那么只需要在s中加入%c和%d等东西就可以实现这一问题了 1 #include <stdio.h> 2 char s[1005]= 阅读全文
摘要:
用f[i][j][k]表示s1前i个字符、s2前j个字符的LCS且包括s3前k个字符的最长前缀,然后对其某一维滚动,实现时细节比较多 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 505 4 int l1,l2,l3,f[2 阅读全文
摘要:
考虑最小割,即最少要去掉多少收益先S向所有机器连边,流量为购买费用;所有机器向工作连边,流量为租借费用;工作向T连边,流量为收益那么对于每一个工作,要么割掉连向T的边,要么购买/租借所有机器,同时由于购买了就一直可以用,所以购买费用直接连向S 1 #include<bits/stdc++.h> 2 阅读全文
摘要:
这个距离就是切比雪夫距离,有一个神奇的东西是说将(x,y)变成(x+y,x-y),然后就是曼哈顿距离,因此转化后对x坐标和y坐标分别统计排序和求和(求前缀和预处理+二分) 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100 阅读全文
摘要:
树链剖分,考虑用线段树维护左端点颜色、右端点颜色和段数,合并时判断中间两个点能否重合即可,注意在树剖时合并的顺序 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define L (k<<1) 5 #def 阅读全文
摘要:
dp,用f[i]表示i划分的方案,直接枚举最后一个数是错误的,因为会导致c重复计数,然后正解十分神奇——当i为奇数,那么分解中一定有1,因此f[i]=f[i-1]当i为偶数若有1,同样转移到f[i-1];没有1,可以将所有因数除以2,即f[i]=f[i-1]+f[i/2],注意对1e9取模 1 #i 阅读全文
摘要:
按照Di排序,从小到大枚举物品,考虑如果直接能选就选上,不能选就考虑替换之前价值最小的来选(显然一定是可行的,只需要在原来选价值最小的时候选这个就行了),这个东西用堆来维护即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 struct ji{ 阅读全文
摘要:
初始如果没有限制,很显然每一头牛高度都是h当只有一个限制,让h[a]到h[b]的高度都减1即可容易发现两个限制不会相交(否则必然矛盾),只会包含或相离,因此没有影响,直接差分/线段树即可(注意:1.不保证a<b;2.可能会有重复) 1 #include<bits/stdc++.h> 2 using 阅读全文
摘要:
很显然是一个最小割的模型,将网格图黑白染色分为两类,黑的向S连工业费用,向T连商业费用,白的反过来即可然后对于相邻的点,连上两个点的C之和(因为会产生两个),当然也可以变成两条边,就不需要存下C矩阵了 1 #include<bits/stdc++.h> 2 using namespace std; 阅读全文
摘要:
构建一棵trie树,然后每一个点的次数*深度取max即可(然而这道题并没有这么简单)首先字符串长度为500000,字符类型52种,需要用邻接表存储(用map就别想了)然后字符串的读入十分麻烦,需要用getchar来读入,还要判掉多余回车最后还有点卡常,要注意常数 1 #include<bits/st 阅读全文
摘要:
根据purfer序列的原理,每一个purfer序列都一一对应了一棵树,每一个点在purfer序列中出现的次数就是它的度数,那么直接用组合数去计算即可,注意要加高精度 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 str 阅读全文
摘要:
考虑将奶牛和牧草放在一起,根据鲜嫩程度排序,那么显然就可以发现一个贪心策略:每一头奶牛一定选择当前剩余的最便宜且符合条件的牧草,然后用一个set维护价格即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 struct ji{ 4 int id, 阅读全文
摘要:
先考虑边的代价,容易发现每一条边都需要走两次,也就是2*边权再考虑点的代价,由于上面的结论,那么就是度数*点权然后就可以构造新的边权为2*原边权+连接点的点权,然后求最小生成树即可注意根还有一个点权,所以再加上根(也就是最小点)的点权即可 1 #include<bits/stdc++.h> 2 us 阅读全文
摘要:
记每一个数向比他大的数合并时的代价为这个数字的代价,显然除了最大值以外,每一个数都有一个代价,那么这个代价和就是最终答案考虑最小化这个代价和,也就是让每一个数的代价最小,显然这个代价不会小于向左和右第一个比他大的数中较小的数,然后这样的方案也很好构造,这个东西用单调栈来处理即可 1 #include 阅读全文
摘要:
ans肯定不会超过n,因为我们可以每一列都放一个矩阵考虑减小答案,肯定是要放横的,也就是让两个高度一样的矩阵同时被消除掉,那么中间不能存在比他们低的矩阵问题即判断一个点之前第一个小于等于它的点是不是等于他(等于就ans-1),然后用单调栈维护之前的递减即可 1 #include<bits/stdc+ 阅读全文
摘要:
问题相当于要求每一个在学校的人都能睡在某一张认识的在校生的床上,很显然是二分图匹配,将在学校的人(不是在校生或不回家)与床(在校生且认识或本人)连边,判断是否有完美匹配即可(注意连边和清空) 1 #include<bits/stdc++.h> 2 using namespace std; 3 #de 阅读全文