多校NOIP27
T1:
首先对于这类题型,由于排序并不会影响问题的决策
不妨将其排序寻找突破点,考虑问题的关键信息之一为可
以无限次交换b,问题转化为对于a分配b使得代价最小。
考虑发现路径总长是一定的,那么显然的贪心策略为
让权值大的走最短的路,权值小的走最长的路,那么由于
出栈时间不同导致距离不同,我们显然要使得距离方差尽
可能大。
因此利用栈模拟,预处理出美中距离的方案数,在将
权值贪心进行分配即可
考场错误之处在于理解错题意导致长时间调试代码无
法通过,心态炸裂。
T2:
mex相关DP,考场错误之处在于发现短时间并没有思
路转而打其余题的暴力。
考虑mex在序列上一个很套路的性质为单调不降,那
么考虑简化问题,当固定序列的一个端点时如何计算,维
护出一个桶即可
考虑首先暴力DP,定义f[j]表示以i为左端点,j为右端
点,区间mex值为k的方案数,时间复杂度O(n^3)
考虑对于DP过程进行优化,考虑枚举mex是否可以简
化,考虑若若干段区间mex值为k,那么全局mex一定为k,
这启发我们反向思考,若全局mex为k,发现每一段mex只
能为k,否则反证,全局mex一定更小
因此取全局mex即可,那么考虑优化DP过程,发现mex
与端点单调趋势相同,因此双指针维护位置即可
T3:
考场错误点在于打出部分分后考虑时间未与暴力进行
对拍而去思考其他题的正解,能对拍一定要对拍,即使出
正解思路也要先打暴力进行对拍
考虑利用题目的要求,路径端点大小的抉择,对于树
上路径问题一种常见打法为点分治,然而并无法很好利用
编号大小关系。
这里是一个新知识,重构树,由于树上简单路径唯一
那么当处理树上路径的问题时,根据问题规模与要求,可
以将原树重构,一般有两种方法:1:重构点集,对于本题
而言,我们并不在乎路径具体是什么,只需要知道整条路
上两端点为极值,因此考虑构造这样一棵树:两点路径间
LCA处即为两点路径上端点最值,显然这会破坏原树结构
但是对于本题而言并不重要。
因此重构树,一个建立小根堆结构,一个建立大根堆
结构,那么我们要求的实际上就是满足两点在两棵树上互
为祖先关系,这是一种偏序问题,考虑首先在一棵树上解
决一维,显然的dfs序处理祖先关系,另一棵树上树状数组
查询对应关系数即可
另外重构树的另一种形式为边重构,即两点LCA处为
两点路径上边最值,那么同样的构造思路,将边视做虚点
具体构造方法为,考虑性质,先考虑两个点的情况再
注意拓展即可
代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define I int 4 #define C char 5 #define B bool 6 #define V void 7 #define S short 8 #define D double 9 #define LL long long 10 #define LLL __int128 11 #define LD long double 12 #define LLD __float128 13 #define UI unsigned int 14 #define UL unsigned long long 15 #define lowbit(x) (x & -x) 16 #define ot(x) cout << #x << " = " << x << " ", 17 #define debug cout << "It's Ok Here !" << endl; 18 #define FP(x) freopen (#x,"r",stdin) 19 #define FC(x) freopen (#x,"w",stdout) 20 #define Tem template<typename T> 21 #define memset(name,val,typ,len) memset (name,val,sizeof (typ) * (len)) 22 #define memcpy(name1,name2,typ,len) memcpy (name1,name2,sizeof (typ) * (len)) 23 24 struct A1 {I a,b;}; 25 inline I read () { 26 I x (0), y (1); C z (getchar ()); 27 while (!isdigit (z)) { if (z == '-') y = -1; z = getchar (); } 28 while ( isdigit (z)) x = x * 10 + (z & 15), z = getchar (); 29 return x * y; 30 } 31 I top; C prt[40]; 32 inline V print (LLL x,C z) { 33 if (x == 0) putchar ('0'); 34 if (x < 0) putchar ('-'), x = -x; 35 while (x) prt[++top] = x % 10, x /= 10; 36 while (top) putchar (prt[top --]); 37 putchar (z); 38 } 39 Tem inline T abs (T &a) { return a >= 0 ? a : -a; } 40 Tem inline V Max (T &a,T b) { a = a > b ? a : b; } 41 Tem inline V Min (T &a,T b) { a = a < b ? a : b; } 42 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; } 43 #ifdef mod 44 Tem inline V Mod1 (T &a,T b) { a = a + b > mod ? a + b - mod : a + b; } 45 Tem inline V Mod2 (T &a,T b) { a = a - b < 0 ? a - b + mod : a - b; } 46 Tem inline T Mod3 (T a,T b) { return a + b > mod ? a + b - mod : a + b; } 47 Tem inline T Mod4 (T a,T b) { return a - b < 0 ? a - b + mod : a - b; } 48 #endif 49 inline A1 operator + (const A1 &a,const A1 &b) { return {a.a + b.a,a.b + b.b}; } 50 inline A1 operator - (const A1 &a,const A1 &b) { return {a.a - b.a,a.b - b.b}; } 51 inline B operator < (const A1 &a,const A1 &b) { return a.a == b.a ? a.b < b.b : a.a < b.a; } 52 const I N = 2e6 + 3; 53 UL ans; 54 I n,f[N]; 55 struct RE {I to,nxt;} e2[N]; 56 struct E {I to,nxt;} e1[N << 1]; 57 I tot1,head1[N],tot2,head2[N],cnt,l[N],r[N]; 58 I get (I x) { return x == f[x] ? x : f[x] = get (f[x]); } 59 struct BIT { 60 I c[N]; 61 inline V insert (I x,I y) { 62 for (;x <= n;x += lowbit (x)) 63 c[x] += y; 64 } 65 inline I secque (I x,I y) { 66 I ans (0); -- x; 67 for (; x ;x -= lowbit (x)) 68 ans -= c[x]; 69 for (; y ;y -= lowbit (y)) 70 ans += c[y]; 71 return ans; 72 } 73 }B1; 74 V Dfs1 (I x) { l[x] = ++ cnt; for (I i(head2[x]); i ;i = e2[i].nxt) Dfs1 (e2[i].to); r[x] = cnt; } 75 V Dfs2 (I x) { 76 ans += B1.secque (l[x],r[x]); 77 B1.insert (l[x], 1); 78 for (I i(head2[x]); i ;i = e2[i].nxt) 79 Dfs2 (e2[i].to); 80 B1.insert (l[x],-1); 81 } 82 signed main () { 83 n = read (); 84 for (I i(1);i <= n; ++ i) { 85 I x (read ()); if (x == 0) continue; 86 e1[++tot1] = {i,head1[x]}, head1[x] = tot1; 87 e1[++tot1] = {x,head1[i]}, head1[i] = tot1; 88 } 89 for (I i(1);i <= n; ++ i) { 90 f[i] = i; 91 for (I j(head1[i]),y(e1[j].to); j ;j = e1[j].nxt,y = e1[j].to) if (y < i) { 92 I tmp1 (get (y)); 93 e2[++tot2] = {tmp1,head2[i]}, head2[i] = tot2, f[tmp1] = i; 94 } 95 } 96 Dfs1 (n), tot2 = 0, memset (head2,0,I,n + 1); 97 for (I i(n);i >= 1; -- i) { 98 f[i] = i; 99 for (I j(head1[i]),y(e1[j].to); j ;j = e1[j].nxt,y = e1[j].to) if (y > i) { 100 I tmp1 (get (y)); 101 e2[++tot2] = {tmp1,head2[i]}, head2[i] = tot2, f[tmp1] = i; 102 } 103 } 104 Dfs2 (1); 105 printf ("%llu\n",ans); 106 }