多校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 }
View Code

 

posted @ 2021-11-12 06:08  HZOI_LYM  阅读(36)  评论(0编辑  收藏  举报