Codeforces 1119D(贡献计算)】的更多相关文章

题目传送 排序看一看. 关键点在于发现性质: 算一个点的贡献时: 1.与后一个有重叠.\[当 a[i] + r >= a[i + 1] + l, 即 r - l >= a[i + 1] - a[i] 时\]a[i] 与 a[i+1] 重叠的部分,都算在a[i+1]里,则a[i]的贡献为:a[i+1] - a[i] 2.无重叠.r - l + 1 3.a[n]的贡献一定是r - l + 1 因此再把差值排序一下二分答案O(1)算出即可 const int maxn = 1e5 + 5; int…
题意:给你一个长度为n的字符串,定义两个字符串的相关度为两个串对应的子串中第一个串字典序大于第二个串的个数.现在给你相关度,和第二个串,问满足条件的第一个串有多少个? 思路:设dp[i][j]为填了前i个字符,后面的字符和s相同,相关度为j的方案数.现在有两种转移: 1:i位置填的字符大于s[i], 那么我们假设i前面第一个与s不相等的位置是l(即s[l + 1]到s[i]是相等的), 那么相当于左端点在[l + 1, i], 右端点在[i, n]的区间都会产生贡x献,那么从dp[l][j -…
要点 容易想到排序,然后对于每个数: 人的惯性思维做法是:\(a[i]*(rank1的+rank2的+-)\).然而解法巧妙之处在于直接把所有的加和当成一个系数,然后先假装所有情况系数都是1,接着往上加,树状数组记录着所有之前比它小的数的情况,只有这些小的数也同时存在的区间才会增大它的系数.而且只在乎数量,不关注具体方案. const int maxn = 5e5 + 5; const int mod = 1e9 + 7; int n, pos[maxn]; ll a[maxn]; ll ans…
关键点在于:全排列中,任意两点u.v相邻的次数一定是(n - 1)! * 2次,即一个常数(可以由高中数学知识计算,将这两个点捏一起然后全排列然后乘二:或者用n! / C(2, n)). 这之后就好算了,每条边算一下子树size对吧,乘法原理就是贡献次数,乘以边权加一起就行了. 所以不是dfs就行了吗,跟dp有啥关系…… PS:变量名起的不行,不该叫inv,而是fac,代表阶乘 ; ; int n, tot; int size[maxn]; struct Edge { int to, nxt;…
Then n - 1n−1 lines follow. ii-th line contains two integers f_{a_i}(1 \le f_{a_i} < i)fai​​(1≤fai​​<i), w_i(0 \le w_i \le 10^{18})wi​(0≤wi​≤1018) —The parent of the ii-th node and the edge weight between the ii-th node and f_{a_i} (ifai​​(istart fr…
题面 传送门 分析 先考虑\(O(nk)\)的做法,先按s从小到大排序,每个串的数显然形成了n个连续区间\([s_i+l,s_i+r]\),且这些区间的左端点升序排列,然后把区间合并就可以知道有多少个不同的数了 然后考虑优化 对于s[i]产生的区间,我们考虑s[i]和s[i+1]产生的区间之间的间隔 若\(s_i+r \leq s_{i+1}+l\),即\(r-l \leq s_{i+1}-s_i\) ​ 则说明s[i]产生的区间和s[i+1]产生的区间不相交,答案增加\((s_i+r)-(s_…
题意及思路:https://blog.csdn.net/mmk27_word/article/details/93999633 第一次见这种DP,有点像退背包的思想,如果发现有可能因为字母相同和前面算重时,把这种情况减去. 代码: #include <bits/stdc++.h> #define LL long long using namespace std; const int maxn = 110; int pre[30]; LL dp[maxn][maxn]; char s[maxn]…
题意:给你一个数组,数组每次每个数都+1,有q次查询每一查询+L到+R中出现的所有不重复的数字个数. +L到+R其实就相当于是0到+(R-L+1) 感觉自己写的好啰嗦,直接上代码加注释: 1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #define ll long long 5 using namespace std; 6 7 ll q[100100]={0},p[100100]={0}…
https://codeforces.com/contest/1060/problem/E 题意 给一颗树,在原始的图中假如两个点连向同一个点,这两个点之间就可以连一条边,定义两点之间的长度为两点之间的最少边数,求加边之后任意两点长度之和 思路 一看到求任意两点,知道需要用每条边的贡献计算(每条边使用了多少次) 每条边的贡献等于边左边的点数*边右边的点数 然后就一直不知道怎么解决加边后的问题,不知道要标记哪些东西,怎么减去 单独看一条路径,加边之后, 假如边数是偶数的话,边数/2 假如边数是奇数…
https://codeforces.com/contest/1151/problem/E 题意 一条长n的链,每个点上有值\(a[i]\),定义\(f(l,r)\)为该区间的\(值\)所代表的点留下来后的联通块数量,求\(\sum^n_{l=1} \sum^n_{r=1} f(l,r)\) 题解 计算贡献,计算每个点留下后作为联通块的第一个点的情况数就是这个点的贡献 代码 #include<bits/stdc++.h> #define ll long long using namespace…