【Henu ACM Round#16 E】Paths and Trees】的更多相关文章

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 感觉很像一道最短路. 然后就试了一发. 结果真的是.. 只要用一个优先队列优化的dijkstra算法求出每个点的最短路上的前一个点是什么就可以了. 相同大小的话.取每个边的前一个边的边权较小的那个. 然后把每个点的前缀边输出就好. [代码] #include <bits/stdc++.h> #define ll long long using namespace std; const int N = 3e5; struct a…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 先搞一条a到b的路径 a c x3 x4 x5....xn-2 d b 然后第二个人的路径可以这样 c a x3 x4 x5...xn-2 b d 也即加两条边[a,x3] [xn-2,b] 所以最少只需要n+1条边. (尽量让边共用,只有两条边是需要特殊加进去的 (可以这样理解,加一条边的话,无论怎么加都不够的.所以加两条肯定是最优的了. 这样贪就好了 但是n=4的时候:' 会发现两对起点和终点中肯定有一对是有一条边**直接相…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] KMP算法可以把"i前缀"pre[i] 分成ssssst的形式 这里t是s的前缀. 然后s其实就是pre[i]中的前 i+1-f[i]个字符组成的 字符串. 特殊的,t可能就是一个空串. 比如abcdefg 这里f是kmp算法中的f数组 然后t有两种可能 ① t==s 这样的话,整个前缀就是 sssssss..ss了 这里有(i)/(i-f[i])个s 设为num; 我们可以用这些s来构造ababababa的形式. 则…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 看看什么时候t[i]-t[i-1]>15. 输出t[i-1]+15就好. 不存在这样的i就输出min(t[n]+15,90) [代码] #include <bits/stdc++.h> using namespace std; int n; int t[100]; int main() { cin >> n; for (int i = 1;i <= n;i++)cin>>t[i]; for…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] O(n^2)枚举每一个区间. 然后维护这个区间里面的"统治数字"是什么. 对于每个区间cnt[统治数字]++; [代码] #include <bits/stdc++.h> using namespace std; const int N = 5000+10; int n; int t[5000+10]; int num[5000+10],cnt[N]; int main() { ios::sync_with…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 根据题意:先明确以下规则: 1.如果两个点之间没有边,那么这两个点只能是a或c,且不能相同 2.如果两个点之间有边,那么他们之间的差的绝对值<=1 那么对于点i,如果它和所有的点都相连了,那么就干脆把他变成b. 这样其他点无论选什么都和它没有关系,其他点选什么都可以了 接下里,找到任意一个点j,且点j没有和所有的点相连. 显然这个点只能为a或c,因为它和某个点之间没有边.[规则1] 那么我们就让这个点j设置为a; ①然后对于和j…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 要求把连续的一段li..ri的边全都删掉. 然后求剩下的图的联通数 如果暴力的话 复杂度显然是O(k*m)级别的. 考虑我们把li..ri全都删掉. 接下来要做两件事. 第一是把1..li-1这些边连起来. 并查集1 然后是把ri+1..m这些边连起来. 并查集2 然后把并查集1和并查集2合并在一起求联通分量就好 两个并查集合在一起可以在线性复杂度内完成. 那么花费的时间就在1..li-1和ri+1,,m这两个并查集的获取上.…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 把B提取出来就是一个等比数列了. 求和一下会发现是这种形式. \(B*\frac{(A^n-1)}{A-1}+A^n*x\) 则求一下乘法逆元 写个快速幂就好 A-1的逆元就是\((A-1)^{MOD-2}\) 要注意A=1的情况. 然后n最大可能为10^18 所以乘的时候要先对其取模 不然会乘爆 [代码] #include <bits/stdc++.h> #define LL long long using namespac…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 肯定是这样 先放k-1个,然后空1个,然后再放k-1个.然后再空1个.. 以此类推. 然后如果(n/k)*(k-1)+n%k>=m的话 那么答案显然就是m,因为不会出现乘2的情况. 否则. 那么只能让某些位置乘2了. 那么什么地方乘呢? 肯定是越前面越早乘越好. 那么temp=m-((n/k)*(k-1)+n%k)就是需要多乘2的次数. 从左往右放入那n/k个空位置中的前temp个就好 然后会发现前temp个连续的k块的递推式…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 如果写过n皇后问题. 肯定都知道 某个点(i,j)和它在同一条对角线上的点分别是i+j的值和i-j的值相同的点. 然后会发现选择的两个点其实就对应了两组i+j和i-j 且每组i+j和i-j i+j的奇偶性和i-j的奇偶性要是一样的 假设第一组i+j和i-j的奇偶性都是x 第二组i+j和i-j的奇偶性是y 那么x和y要不一样才行. 不然会有重复的点. 会发现只要满足这个就能不重复了. (画图就知道了 那么我们处理出来i+j和i-j…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 如果是一个k-string的话. 考虑最后的串假设形式为sss..ss(k个s) 则s中出现的字母,整个串中最后出现的次数肯定为k的倍数. 如果某个字母出现的次数不为k的倍数. 那么直接输出-1 否则. 我们把每个字母出现的次数/k分到每个部分就好. [代码] #include <bits/stdc++.h> #define LL long long #define rep1(i,a,b) for (int i = a;i &…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] a1+a2+...+ak<a2+a3+...ak+1 ->a1<ak+1 a2+a3+...+ak+1<a3+a4+...+ak+2 ->a2<ak+2 类似还可以推出 a3<ak+3 a4<ak+4 ... 则有 a1<ak+1<a2k+1<a3k+1... a2<ak+2<a2k+2<a3k+2... ... 也就是每隔k个要是递增的. 你的任务就是维…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 考虑,为什么一个连通块里面的空格没有变成一个矩形? 如果不是形成矩形的话. 肯定是因为某个2x2的单张方形里面. 只有一个角是墙.其他角都是空的正方形. 举一些例子. ...* *... 可以看到这个连通块不是长方形. 就是因为有 .. *. 和 .* .. 如果我们把这两个角上的墙给删掉的话. 显然就能得到一个矩形了. 根据这个作为启发. 我们可以将整张图里面所有的2x2的正方形里面的"角"都给删掉. 这样的话,就能…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 如果我们对某一个位置i操作两次的话. 显然结果就和操作一次一样. 因为第一次操作过后1..i这些数字就变成是互质的了. gcd为1.那么除过之后没有影响的. 然后.就是要明白 那个f(x)函数的意义.其实就是问你x质因数分解之后,其中好的质数和坏的质数的差是多少. 也即有多少个好因数,多少个坏因数. (以下的gcd(i)都指的是a[1..i]这些数字的gcd 然后考虑我们在第i个位置进行了一次操作. 显然他会对后面的数字造成影响…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 所给的li,ri是左括号从左到右的顺序给的. (且注意长度是2*n 现在我们先把第一个左括号放在第1个位置. 然后考虑第二个位置. 如果这个位置能放右括号和第一个匹配(位置满足在1+l[i]..1+r[i]之间. 那么我们就在第二个位置放一个右括号就好了. (如果我们作死不放右括号的话,那就只能放左括号了->一定要放一个括号的 那么我们就只能先匹配这一个左括号了,而前一个左括号可能在第3个位置就不能匹配了. 这就会造成错解. 也…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 找规律. 1,13,37.... 6n(n-1) + 1 [代码] #include <bits/stdc++.h> #define ll long long using namespace std; ll n; int main(){ ios::sync_with_stdio(0),cin.tie(0); cin >>n; cout<<6*n*(n-1) + 1<<endl; return…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 一开始所有的数字单独成一个集合. 然后用v[0]和v[1]记录集合的和为偶数和奇数的集合它们的根节点(并查集 然后先让v[0]的大小变成p //奇数+偶数是奇数 //奇数+奇数是偶数 //偶数+偶数是偶数 如果v[0].size < p 那么随便让两个和为奇数的集合,让他们合并在一起,加入到偶数集合中,那么v[0].size++,v[1].size-=2了 如果v[0].size > p 那么有两种方法  1.让两个偶数集合合…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 处理处所有的字符串可能的样子. 存在map里面就好. [代码] #include <bits/stdc++.h> using namespace std; const string S[8] = {"vaporeon", "Jolteon", "Flareon", "Espeon", "Umbreon", "Leafe…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 根据时间和原分数. 算出对应的分数就可以了. [代码] #include <bits/stdc++.h> using namespace std; int a,b,c,d; int main() { cin >> a >> b >> c >> d; int temp1 = max(a/10*3,a-a/250*c); int temp2 = max(b/10*3,b-b/250*…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 看看有没有(n-2)*180/n等于输入的a就好. [代码] #include <bits/stdc++.h> using namespace std; int main() { int T; cin >> T; while (T--){ int a; cin >> a; bool ok = false; //(n-2)*180/n for (int n = 3; ;n++){ int temp = (…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 这一题和这一题很像 (链接 ) 会发现如果a[i]!=b[i]那么就按下i就好了. 然后改变和他相邻的点. 此后a[i]再也不可能和b[i]相同了. (其他点无论怎么按b[i]只会变大) 但是这样直接暴力写会超时->O(N^2). 则写一个队列. 处理和他相邻的点的时候. 如果发现a[y]==b[y] 就重新入队. 因为可以保证每个点最多操作一次. 所以复杂度就是O(n+m)的了. [代码] #include <bits/st…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 紫书上的原题: 链接 [代码] #include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e5; ll m,c1,c2,v1,v2; int main() { #ifdef LOCAL_DEFINE freopen("rush_in.txt","r",stdin); #endif i…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 考虑l..r这个区间. 且r是满足a[r]-a[l]<=d的最大的r 如果是第一个找到的区间,则直接累加C(r-l+1,3); 然后l++ 然后考虑这个区间之后的下一个区间[l+1,R],这里R是满足a[R]-a[l+1]<=d的最大的R 如果R==r的话,l=l+1,continue; 否则. 如果l+1>r的话累加C(R-(l+1)+1,3); 如果l+1<=r的话 显然l..r和l+1..R之间有一个公共的部…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 优先把不是10的倍数的变成10的倍数. (优先%10比较大的数字增加 如果k还有剩余. 剩下的数字都是10的倍数了. 那么先加哪一个都可以了. [代码] #include <bits/stdc++.h> using namespace std; const int N = 1e5; int a[N+10],n,k; int b[N+10]; int point = 0; int main() { ios::sync_with_…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 从右往左维护最大值. 看到比最大值小(或等于)的话.就递增到比最大值大1就好. [代码] #include <bits/stdc++.h> using namespace std; const int N = 1e5; int a[N+10],n; int main() { cin >> n; for(int i = 1;i <= n;i++) cin >> a[i]; int now=0; fo…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 模拟题. 两个一起用->min(a,b); 剩下的除2加上去就好 [代码] #include <bits/stdc++.h> using namespace std; int a,b; int main() { cin >> a >> b; cout<<min(a,b)<<' '<<abs(a-b)/2<<endl; return 0; }…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 每个数字有3种选择. 1.选中它. 2.选中它且加阶乘符号 3.不选中它(即计算和的时候不考虑它) 如果我们直接暴力写的话复杂度是\(3^{25}\) 寻求优化. 我们可以用Meet-in-the-middle这个方法. 先求出1..n/2这些数字的组合方式. 用map<ll,ll> dic[25]来存它们的和. dic[i][j]表示前n/2个数字中选了i个[2]状态的数字,和为j的方案数. 则我们再穷举n/2+1..n这些…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 假设现在每个人收到的信息条数存在cnt里面 那个人猜的条数为target 则如果cnt[i]==target[i] 则我们就让第i个人来就好了. 因为s[i][i]=1恒成立. 所以第i个人它的cnt个数肯定递增了. 因此第i个人的cnt值和target值肯定再也不会相同了. (其他人如果来的话,只会让这个人的cnt值越来越大,离target越来越远 所以如果对每个人都这么做的话. 最后肯定可以让所有人的cnt值都和target…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 用cnt[i]记录数字i出现的次数就好. 然后i从1e6逆序到1 如果cnt[i+1]和cnt[i]>0同时成立的话. 那么得到一条边.加入到vector中. 然后 如果cnt[i]>1 则cnt[i]-=2 加入i到vector中,直到cnt[i]<=1为止. 注意这两个判断的先后顺序. 否则 5 4 4 3会被认为无解. vector的大小如果大于等于2了. 就说明找到一个矩形. [代码] #include <…
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] m比较小 <=1000 a[i]直接看成a[i]%m就可以了. 有n个0..999之间的整数.. 如果有一个0那么就直接输出Yes. 否则要用那些数字凑0 则用cnt[0..999]记录每个数字出现的个数. 即n个物品,每个物品cnt[i]个. 然后凑和为0 ->多重背包. 但每个物品的数量可能很多. 所以加一个二进制优化就好了. 把每个物品的数量转化成二进制. 转换成01背包的问题. (物品的数目大概在1000*log2(1…