T1 少膜一个,T3 暴力写挂

强势 rank1 -> rank2

一场比赛两道线段树分治,给力

T1 password

给你 m 个禁止字符串,求长度为 n 的所有字符串中至少包含这些禁止字符串各一次的字符串数量

$n \leq 10^9,m \leq 4,\sum len \leq 50$

sol:容斥一下就变成了“m 个禁止字符串,一个都不出现的字符串数量”

这个可以转化成从 init 节点走 x 步走不到任意一个节点的方案数

矩阵加速即可

需要注意的是状态压缩被卡了,这种状压 + 矩乘可以用容斥来把矩阵变小

比赛的时候因为少膜了一下,挂了一个点

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. #define LL long long
  4. using namespace std;
  5. inline int read()
  6. {
  7. int x = ,f = ;char ch = getchar();
  8. for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
  9. for(;isdigit(ch);ch = getchar())x = * x + ch - '';
  10. return x * f;
  11. }
  12.  
  13. const int N = ;
  14. const int A = ;
  15. const int MOD = ;
  16.  
  17. typedef vector<int> vec;
  18. typedef vector<vec> mat;
  19.  
  20. mat mul(mat &A, mat &B)
  21. {
  22. mat C(A.size(), vec(B[].size()));
  23. for (int i = ; i < A.size(); ++i)
  24. {
  25. for (int k = ; k < B.size(); ++k)
  26. {
  27. for (int j = ; j < B[].size(); ++j)
  28. {
  29. C[i][j] = (C[i][j] + (LL)A[i][k] * B[k][j]) % MOD;
  30. }
  31. }
  32. }
  33. return C;
  34. }
  35.  
  36. mat pow(mat A, int n)
  37. {
  38. mat B(A.size(), vec(A.size()));
  39. for (int i = ; i < A.size(); ++i)
  40. B[i][i] = ;
  41. while (n > )
  42. {
  43. if (n & ) B = mul(B, A);
  44. A = mul(A, A);
  45. n >>= ;
  46. }
  47. return B;
  48. }
  49.  
  50. struct ACAutomata
  51. {
  52.  
  53. int next[N][A], fail[N], end[N];
  54. int root, L;
  55.  
  56. int idx(char ch)
  57. {
  58. return ch - '';
  59. }
  60. int newNode()
  61. {
  62. for (int i = ; i < A; ++i) next[L][i] = -;
  63. end[L] = ;
  64. return L++;
  65. }
  66. void init()
  67. {
  68. L = ;
  69. root = newNode();
  70. }
  71. void insert(char buf[])
  72. {
  73. int len = strlen(buf);
  74. int now = root;
  75. for (int i = ; i < len; ++i)
  76. {
  77. int ch = idx(buf[i]);
  78. if (next[now][ch] == -) next[now][ch] = newNode();
  79. now = next[now][ch];
  80. }
  81. end[now]++;
  82. }
  83. void build()
  84. {
  85. queue<int> Q;
  86. fail[root] = root;
  87. for (int i = ; i < A; ++i)
  88. {
  89. if (next[root][i] == -)
  90. {
  91. next[root][i] = root;
  92. }
  93. else
  94. {
  95. fail[ next[root][i] ] = root;
  96. Q.push( next[root][i] );
  97. }
  98. }
  99. while (!Q.empty())
  100. {
  101. int now = Q.front();
  102. Q.pop();
  103. if (end[ fail[now] ]) end[now]++;
  104. for (int i = ; i < A; ++i)
  105. {
  106. if (next[now][i] == -)
  107. {
  108. next[now][i] = next[ fail[now] ][i];
  109. }
  110. else
  111. {
  112. fail[ next[now][i] ] = next[ fail[now] ][i];
  113. Q.push(next[now][i]);
  114. }
  115. }
  116. }
  117. }
  118.  
  119. int query(int n)
  120. {
  121. mat F(L, vec(L));
  122. for (int i = ; i < L; ++i)
  123. {
  124. for (int j = ; j < L; ++j)
  125. {
  126. F[i][j] = ;
  127. }
  128. }
  129. for (int i = ; i < L; ++i)
  130. {
  131. for (int j = ; j < A; ++j)
  132. {
  133. int nt = next[i][j];
  134. if (!end[nt]) F[i][nt]++;
  135. }
  136. }
  137. F = pow(F, n);
  138. int res = ;
  139. for (int i = ; i < L; ++i)
  140. {
  141. res = (res + F[][i]) % MOD;
  142. }
  143. return res;
  144. }
  145.  
  146. } ac;
  147. int m,n;
  148. char buf[][];
  149. int skr(int x,int t)
  150. {
  151. int res = ;
  152. while(t)
  153. {
  154. if(t & )res = res * x % MOD;
  155. x = x * x % MOD;
  156. t = t >> ;
  157. }return res;
  158. }
  159. signed main()
  160. {
  161. freopen("password.in","r",stdin);
  162. freopen("password.out","w",stdout);
  163. m = read(),n = read();
  164. int qwq = ,qnq = skr(,n);
  165. for(int i=;i<=m;i++)cin>>buf[i];
  166. for(int SS=;SS<=(<<m)-;SS++)
  167. {
  168. int flg = __builtin_popcount(SS),S = (flg & ) ? : -;
  169. ac.init();
  170. memset(ac.next,-,sizeof(ac.next));
  171. memset(ac.fail,,sizeof(ac.fail));
  172. memset(ac.end,,sizeof(ac.end));
  173. for(int i=;i<m;i++)
  174. if(SS & ( << i))ac.insert(buf[i+]);
  175. ac.build();
  176. qwq += (S * ac.query(n));
  177. }
  178. cout<<((((qnq-qwq) % MOD) + MOD) % MOD)<<endl;
  179. return ;
  180. }

T1

T2 paint

APIO2014 特别行动队,但是所有东西都可以为负

额...就是你现在有 n 个人,每个人有权值,你可以把它们分成若干组,第 i 人只能跟 $[i-l,i+r]$ 这些人一组,一组的权值和为 $s$,一组的权值为 $ax^2+bx+c$ ,让你最大化权值

sol:因为一个人只能由 $[i-l,i+r]$ 转移过来,我们可以考虑这个人有贡献的区间,那显然是 $[i+l,min(i+r,n)]$ ,我们可以在线段树这个区间上打上这个人的 tag

然后我们按线段树的 dfs 序扫这个区间,因为这个人有贡献的区间一定在这个人右边,所以处理到这个区间的时候,所有打在上面的 tag 已经处理完毕了

于是我们可以把从这个叶子到根的 logn 层凸包并起来二分

然后就写完了。。

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define DB long double
  4. using namespace std;
  5. inline int read()
  6. {
  7. int x = ,f = ;char ch = getchar();
  8. for(;!isdigit(ch);ch = getchar())if(ch == '-')f = -f;
  9. for(;isdigit(ch);ch = getchar())x = * x + ch - '';
  10. return x * f;
  11. }
  12. const int maxn = ;
  13. const DB inf = (DB)1.0 / 0.0;
  14. int n,l,r;
  15. LL a,b,c;
  16. LL sum[maxn],f[maxn];
  17. void force()
  18. {
  19. for(int i=;i<=n;i++)
  20. {
  21. for(int j=max(i-r,);j<=min(i-l,n);j++)
  22. f[i] = max(f[i],f[j] + a * (sum[i] - sum[j]) * (sum[i] - sum[j]) + b * (sum[i] - sum[j]) + c);
  23. }
  24. cout<<f[n]<<endl;
  25. }
  26. struct point
  27. {
  28. DB x,y;
  29. int id;
  30. point operator - (const point &b)const{return (point){x - b.x,y - b.y,id};}
  31. bool operator < (const point &b)const{return x < b.x;}
  32. DB operator * (const point &b)const{return x * b.y - y * b.x;}
  33. }ps[maxn];
  34. vector<int> Items[maxn << ],ch[maxn << ];
  35. DB dp[maxn],Sum[maxn];
  36. int q[maxn],top;
  37. #define ls (x << 1)
  38. #define rs ((x << 1) | 1)
  39. void Insert(int x, int l, int r, int L, int R, int id)
  40. {
  41. if(L <= l && r <= R){Items[x].push_back(id);return;}
  42. int mid = (l + r) >> ;
  43. if(L <= mid) Insert(ls,l,mid,L,R,id);
  44. if(R > mid) Insert(rs,mid + ,r,L,R,id);
  45. }
  46. inline DB trans(int frm,int targ){return (DB)dp[frm] + (DB)a * (Sum[targ] - Sum[frm]) * (Sum[targ] - Sum[frm]) + (DB)b * (Sum[targ] - Sum[frm]) + c;}
  47. void CDQ(int x,int l,int r)
  48. {
  49. int tp = ;
  50. for(int i=;i<Items[x].size();i++)
  51. {
  52. int to = Items[x][i];
  53. ps[++tp] = (point){Sum[to],dp[to] + (DB)a * Sum[to] * Sum[to] - (DB)b * Sum[to],to};
  54. }
  55. if(tp)
  56. {
  57. sort(ps + ,ps + tp + );top = ;
  58. q[++top] = ;
  59. for(;q[] <= tp && ps[q[]].y == -inf;++q[]);
  60. for(int i=q[]+;i<=tp;i++)
  61. {
  62. if(ps[i].y == -inf) continue;
  63. for(;top > && ((ps[q[top]] - ps[q[top-]]) * (ps[i] - ps[q[top]])) >= ;--top);
  64. q[++top] = i;
  65. }
  66. if(q[] > tp)top = ;
  67. for(;top && ps[q[top]].y == -inf;--top);
  68. if(top)for(int i=;i<=top;i++)ch[x].push_back(ps[q[i]].id);
  69. }
  70. if(l == r)
  71. {
  72. int now = x;
  73. while(now)
  74. {
  75. int nl = ,nr = ch[now].size() - ;
  76. while(nl < nr)
  77. {
  78. int md = (nl + nr) >> ;
  79. if(md < (ch[now].size() - ) && trans(ch[now][md],l) <= trans(ch[now][md+],l))nl = md + ;
  80. else nr = md;
  81. }
  82. if(ch[now].size())dp[l] = max(dp[l],trans(ch[now][nl],l));
  83. now = now >> ;
  84. }
  85. return;
  86. }
  87. int mid = (l + r) >> ;
  88. CDQ(ls,l,mid);CDQ(rs,mid + ,r);
  89. }
  90. void solve()
  91. {
  92. for(int i=;i<=n;i++)Sum[i] = sum[i];
  93. for(int i=;i<=n;i++)dp[i] = -inf;
  94. for(int i=;i<=n;i++)Insert(,,n,i + l,min(i+r,n),i);
  95. //cout<<111<<endl;
  96. CDQ(,,n);LL ans = floor(dp[n]);
  97. printf("%lld\n",ans);
  98. //cout<<ret<<endl;
  99. }
  100. int main()
  101. {
  102. freopen("paint.in","r",stdin);
  103. freopen("paint.out","w",stdout);
  104. n = read();a = read();b = read();c = read();l = read();r = read();
  105. for(int i=;i<=n;i++)sum[i] = sum[i - ] + read();
  106. //if(n <= 1000)force();
  107. //else
  108. solve();
  109. }

T2

T3 route

树上找一条链,满足

1.链上最长边和最短边的差不超过 m

2.链上最短边 $\times$ 链上边权和 最大

$n,m \leq 2 \times 10^5$

sol:

如果没有 m 的限制,就是一个点分治

对于分治中心往下的每一条链,我们记一个信息 $(mi,su)$ 表示这条链上最小值为 $mi$ ,权值和为 $su$

按 $mi$ 的下标插入树状数组,每次查询即可

注意每次按儿子顺序正着做一遍,反着做一遍·

这样写可以 $O(nlog^2n)$ 拿到 80 分

或者我们用 LCT 维护子树信息,很好想但。。。不太可写

正解基于下面一个结论:如果树上一个连通块 u 的一条直径为 $u_i,u_j$ ,一个连通块 v 的一条直径为 $v_i,v_j$

则 $(u_i,v_i),(u_i,v_j),(u_j,v_i),(u_j,v_j)$ 其中至少一个为连通块 u,v 的并集的直径

于是对于 80 分我们可以按从大到小加入每条边然后直接统计答案

对于 100 分,除了加入,我们还有删除操作

这个时候我们可以线段树按时间分治,用一个可撤销的并查集来维护连通性

或者 LCT

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<queue>
  4. #include<ctime>
  5. #include<cstring>
  6. #include<algorithm>
  7. #define dwn(i,s,t) for(int i=s;i>=t;i--)
  8. #define rep(i,s,t) for(int i=s;i<=t;i++)
  9. #define ren for(int i=first[x];i;i=next[i])
  10. using namespace std;
  11. inline int read() {
  12. int x=,f=;char c=getchar();
  13. for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
  14. for(;isdigit(c);c=getchar()) x=x*+c-'';
  15. return x*f;
  16. }
  17. typedef long long ll;
  18. typedef pair<int,int> Pair;
  19. const int maxn=;
  20. struct Edge {
  21. int u,v,w;
  22. bool operator < (const Edge& ths) const {return w>ths.w;}
  23. }E[maxn];
  24. int n,lim,first[maxn],next[maxn<<],dis[maxn<<],to[maxn<<],e;
  25. void AddEdge(int u,int v,int w) {
  26. to[++e]=v;dis[e]=w;next[e]=first[u];first[u]=e;
  27. to[++e]=u;dis[e]=w;next[e]=first[v];first[v]=e;
  28. }
  29. ll mn[][maxn*],dep[maxn];
  30. int pos[maxn*],cnt;
  31. void dfs(int x,int fa) {
  32. mn[][++cnt]=dep[x];pos[x]=cnt;
  33. ren if(to[i]!=fa) {
  34. dep[to[i]]=dep[x]+dis[i];
  35. dfs(to[i],x);
  36. mn[][++cnt]=dep[x];
  37. }
  38. }
  39. int Log[maxn*];
  40. void init() {
  41. Log[]=-;rep(i,,cnt) Log[i]=Log[i>>]+;
  42. for(int j=;(<<j)<=cnt;j++)
  43. for(int i=;i+(<<j)-<=cnt;i++)
  44. mn[j][i]=min(mn[j-][i],mn[j-][i+(<<j-)]);
  45. }
  46. ll query(int x,int y) {
  47. ll ans=dep[x]+dep[y];x=pos[x];y=pos[y];if(x>y) swap(x,y);
  48. int k=Log[y-x+];
  49. return ans-*min(mn[k][x],mn[k][y-(<<k)+]);
  50. }
  51. Pair A[maxn];
  52. Pair merge(Pair A,Pair B) {
  53. int x1=A.first,y1=A.second;
  54. int x2=B.first,y2=B.second;
  55. int x=x1,y=y1;
  56. if(query(x2,y2)>query(x,y)) x=x2,y=y2;
  57. if(query(x2,y1)>query(x,y)) x=x2,y=y1;
  58. if(query(x2,x1)>query(x,y)) x=x2,y=x1;
  59. if(query(y2,x1)>query(x,y)) x=y2,y=x1;
  60. if(query(y2,y1)>query(x,y)) x=y2,y=y1;
  61. return make_pair(x,y);
  62. }
  63. int pa[maxn],size[maxn];
  64. int findset(int x) {return x==pa[x]?x:findset(pa[x]);}
  65. int end[maxn];
  66. struct Data {
  67. int x,y,pax,sizey;
  68. ll ansv;
  69. Pair datay;
  70. }S[maxn];
  71. int ToT;
  72. ll maxlen,ans;
  73. void link(int x,int y) {
  74. x=findset(x);y=findset(y);
  75. if(x==y) return;
  76. if(size[x]>size[y]) swap(x,y);
  77. S[++ToT]=(Data){x,y,pa[x],size[y],maxlen,A[y]};
  78. pa[x]=y;if(size[x]==size[y]) size[y]++;A[y]=merge(A[y],A[x]);
  79. maxlen=max(maxlen,query(A[y].first,A[y].second));
  80. }
  81. void restore(int begin) {
  82. while(ToT!=begin) {
  83. int x=S[ToT].x,y=S[ToT].y,pax=S[ToT].pax,sizey=S[ToT].sizey;
  84. maxlen=S[ToT].ansv;Pair z=S[ToT--].datay;
  85. pa[x]=pax;size[y]=sizey;A[y]=z;
  86. }
  87. }
  88. int ls[maxn<<],rs[maxn<<],rt;
  89. void buildtree(int& o,int l,int r) {
  90. o=++ToT;if(l==r) return;
  91. int mid=l+r>>;
  92. buildtree(ls[o],l,mid);buildtree(rs[o],mid+,r);
  93. }
  94. int first2[maxn<<],nxt2[maxn*],id[maxn*];
  95. void AddMark(int x,int val) {
  96. id[++cnt]=val;nxt2[cnt]=first2[x];first2[x]=cnt;
  97. }
  98. void query(int o,int l,int r,int ql,int qr,int val) {
  99. if(ql<=l&&r<=qr) AddMark(o,val);
  100. else {
  101. int mid=l+r>>;
  102. if(ql<=mid) query(ls[o],l,mid,ql,qr,val);
  103. if(qr>mid) query(rs[o],mid+,r,ql,qr,val);
  104. }
  105. }
  106. void solve(int o,int l,int r) {
  107. int begin=ToT;
  108. for(int i=first2[o];i;i=nxt2[i]) link(E[id[i]].u,E[id[i]].v);
  109. if(l<r) {
  110. int mid=l+r>>;
  111. solve(ls[o],l,mid);
  112. solve(rs[o],mid+,r);
  113. }
  114. else ans=max(ans,maxlen*E[l].w);
  115. restore(begin);
  116. }
  117. int main() {
  118. freopen("route.in","r",stdin);
  119. freopen("route.out","w",stdout);
  120. n=read();lim=read();
  121. rep(i,,n-) {
  122. E[i].u=read();E[i].v=read();E[i].w=read();
  123. AddEdge(E[i].u,E[i].v,E[i].w);
  124. }
  125. buildtree(rt,,n-);ToT=;
  126. dfs(,);init();cnt=;
  127. sort(E+,E+n);
  128. rep(i,,n) pa[i]=i,A[i]=make_pair(i,i),size[i]=;
  129. int j=n-;
  130. dwn(i,n-,) {
  131. while(E[i].w-E[j].w>lim) j--;
  132. end[i]=j;query(rt,,n-,i,end[i],i);
  133. }
  134. solve(rt,,n-);
  135. printf("%lld\n",ans);
  136. return ;
  137. }

T3

[冬令营模拟]wzj的题目#1的更多相关文章

  1. [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania

    [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见&quo ...

  2. [冬令营模拟]GTSG2018

    上学期没有去 GTSG,于是今天老师让我们来做一下 GTSG2018 Day1 & Day3 Day1 在上午当成一场考试来搞了,Day3 由于锅太多而且 T3 玄学而被放到下午自学... 上 ...

  3. 6.19 noip模拟题(题目及解析转自 hzwer 2014-3-15 NOIP模拟赛)

    Problem 1 高级打字机(type.cpp/c/pas) [题目描述] 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这种高级打字机设计一个程序 ...

  4. [JZOJ5977] 【清华2019冬令营模拟12.15】堆

    题目 其中n,q≤500000n,q\leq 500000n,q≤500000 题目大意 让你维护一个堆.支持一下操作: 在某个点的下面加上另一个点,然后进行上浮操作. 询问某一点的权值. 思考历程 ...

  5. JZOJ[5971]【北大2019冬令营模拟12.1】 party(1s,256MB)

    题目 题目大意 给你一棵树,在树上的某一些节点上面有人,要用最小的步数和,使得这些人靠在一起.所谓靠在一起,即是任意两个人之间的路径上没有空的节点(也就是连在一起). N≤200N \leq 200N ...

  6. jzoj5990. 【北大2019冬令营模拟2019.1.6】Bear (状压dp)

    题面 题解 我永远讨厌dp.jpg 搞了一个下午优化复杂度最后发现只要有一个小trick就可以A了→_→.全场都插头dp就我一个状压跑得贼慢-- 不难发现我们可以状压,对于每一行,用状态\(S\)表示 ...

  7. jzoj5991. 【北大2019冬令营模拟2019.1.6】Juice

    题面 题解 好迷-- //minamoto #include<bits/stdc++.h> #define R register #define ll long long #define ...

  8. jzoj5989. 【北大2019冬令营模拟2019.1.6】Forest (set)

    题面 题解 为了一点小细节卡了一个下午--我都怕我瞎用set把电脑搞炸-- 观察一次\(1\)操作会造成什么影响,比如说把\(A[i]\)从\(x\)改成\(y\): \(D[x]\)会\(-1\), ...

  9. jzoj5984. 【北大2019冬令营模拟2019.1.1】仙人掌 (分块)

    题面 题解 数据结构做傻了.jpg 考虑每一个节点,它的儿子的取值最多只有\(O(\sqrt {m})\)种,那么可以用一个双向链表维护儿子的所有取值以及该取值的个数,那么对儿子节点修改一个值就是\( ...

随机推荐

  1. 安装android Studio和运行react native项目(基础篇)

    ANDROID_HOME环境变量 确保ANDROID_HOME环境变量正确地指向了你安装的Android SDK的路径. 打开控制面板 -> 系统和安全 -> 系统 -> 高级系统设 ...

  2. [note]一类位运算求最值问题

    [note]一类位运算求最值问题 给定一些数,让你从中选出两个数a,b,每次询问下列中的一个 1.a and b的最大值 2.a xor b的最大值 3.a or b的最大值 神仙们都是FWT,小蒟蒻 ...

  3. Android系统移植与调试之------->如何修改Android自带的apk出现一圈圈类似鸡蛋的花纹

    最近被一个问题烦恼到了,就是android4.1系统自带的Email.文件管理器.信息等apk都出现同一个问题,就是现实在平板上的时候会出现一圈圈类似鸡蛋的花纹. 我想了两种方法来解决,第一种方法没有 ...

  4. 忘记apple id如何更新应用?

    最近ytkah的app有很多更新提示,之前注册的apple id好久没登录了,突然提示说登录需要验证安全问题,哪还记得噢,最要命的是邮箱收到的加密邮件也需要验证.重新注册一个吧,这次要注意保存相关信息 ...

  5. client = new DatagramSocket(LocalPort) 是说端口已经被占用的意思

    ok 现在遇到一个问题,client = new DatagramSocket(LocalPort) 是说端口已经被占用的意思 ref:!!https://community.oracle.com/t ...

  6. LeetCode:最少移动次数使得数组元素相等||【462】

    LeetCode:最少移动次数使得数组元素相等||[462] 题目描述 给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最 ...

  7. Linux通过Shell对文件自动进行远程拷贝备份

    在执行计划任务拷贝文件的时候,用scp命令需要输入密码,这里用公共密钥的方式实现密码的自动输入. 具体操作: 要求:把192.168.0.2机上的test.tar拷贝到192.168.0.3机器的上 ...

  8. Python OOP(1)

    类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中且在函数体之外. ...

  9. Linux内核源码中的likely和unlikely释疑【转】

    本文转载自:https://my.oschina.net/armsky/blog/15320 ikely()与unlikely()在2.6内核中,随处可见,那为什么要用它们?它们之间有什么区别呢? 首 ...

  10. java入门了解15

    1.批处理文件(bat) 简单的说,批处理的作用就是自动的连续执行多条命令 .编写bat处理文件可以使用记事本的方式: 常见批处理文件的命令: echo 表示显示此命令后的字符 tiltle 设置窗口 ...