目录

  • 2018.8.6 正睿暑期集训营 Day3

    • A 亵渎(DP)
    • B 绕口令(KMP)
    • C 最远点(LCT)
    • 考试代码
      • A
      • B
      • C


2018.8.6 正睿暑期集训营 Day3

时间:5h(实际)
期望得分:...
实际得分:...
rating-93 _(:зゝ∠)_

比赛链接

A 亵渎(DP)

题目链接

贪心不对啊,根本不知道该以什么策略。。
最优情况下亵渎应是最后用,此时所有元素都应在1~x内。
f[i][j]表示前i个元素全部变到1~j内(每个整数)的最小花费。则f[i][j]=min(f[i-1][j-1],f[i-1][j])+cost(i->j)。初始时除0全为INF,因为新的j只能从j-1转移。
注意除1外显然不能从0转移。

略错的思路(答案应该一样):
DP,f[i][j]表示当前i个,构成阶梯长为j。
我们还要知道用哪些数构成了阶梯。假设用i放到j的话,那么前i-1个要么也构成了阶梯,要么被减到和i一样。
那么就有两种转移:f[i][j]=min(f[i-1][j-1],f[i-1][j])+cost(i->j)。(不管怎样i都是要削成j的)
在枚举所有i时更新答案就可以了。之前预处理后缀和。
事实上只在最后更新答案就可以,原因见上。。

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=5005;int n,A[N];
LL P,Q,R,f[N];inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}int main()
{n=read(); LL ans=0;for(int i=1; i<=n; ++i) ans+=(A[i]=read());std::sort(A+1,A+1+n);P=read(), Q=read(), R=read(), ans*=Q;f[0]=0;
//  for(int i=1; i<=n; ++i) f[i]=1e15;for(int i=1; i<=n; ++i){LL ai=A[i];f[i]=f[i-1]+(ai>i?Q*(ai-i):P*(i-ai)), f[0]=1e15;//一维得特判一下f[i]。。for(int j=i-1; j; --j)f[j]=std::min(f[j-1],f[j])+(ai>j?Q*(ai-j):P*(j-ai));}for(int i=1; i<=n; ++i)ans=std::min(ans,f[i]+R);printf("%lld\n",ans);return 0;
}

B 绕口令(KMP)

题目链接

一个环删掉一段,剩下的一段也是连续的。它当中不含有相邻的相同字符。如果原串中存在相邻的相同字符,则在这里把环切开,最后会把环切若干段,合法的剩下的段显然是某一段的一部分。
然后判断在合法的段中是否有长\(x\)的合法长度(若存在,则删\(n-x\)个是可以的),即长\(x\)首尾字母不同的段。而再删一段后首尾字母相同就是一段前后缀相同。
判断前后缀是否相同可以直接用KMP/Hash。如果有长为\(l\)的相同前后缀长度,则\(n-l+1\)位置是非法的。拆环为链每次只删后缀就是正确的了。
如果不存在相邻的相同字符,把整个串求一遍就行了。

#include <cstdio>
#include <cstring>
#include <algorithm>
const int N=2e6+5;bool ok[N];
char s[N],t[N];void Calc(int l)
{static int fail[N];static bool ban[N];//  fail[0]=fail[1]=0;for(int i=1,j=0; i<l; ++i){while(j && t[j]!=t[i]) j=fail[j];fail[i+1]=t[i]==t[j]?++j:0;}for(int i=fail[l]; i; i=fail[i]) ban[l-i+1]=1;for(int i=1; i<=l; ++i) if(!ban[i]) ok[i]=1;for(int i=fail[l]; i; i=fail[i]) ban[l-i+1]=0;
}
void Solve()
{int n=strlen(s+1),cnt=0,len=n<<1;for(int i=1; i<=n; ++i) s[i+n]=s[i];for(int i=1; i<len; ++i){t[cnt++]=s[i];if(s[i]==s[i+1]) Calc(cnt), cnt=0;}if(cnt) Calc(cnt);for(int i=0; i<n; ++i) putchar(ok[n-i]+'0');//, ok[n-i]=0;//清空不完a!!for(int i=1; i<len; ++i) ok[i]=0;putchar('\n');
}int main()
{int Cs=1;while(~scanf("%s",s+1))printf("Case %d:",Cs++), Solve();return 0;
}

C 最远点(LCT)

题目链接

动态维护森林中每个点距最远点的距离及其所在树的直径,支持增加、删除边。

LCT,维护每个点到其子树内的最远距离及次远距离。因为树的形态一直在变,用set/heap维护每个点其所有虚子树的 最长延伸距离(hp1)和答案(hp2)。
单独维护每个点左右两棵实子树的最长距离。
因为LCT的Splay形态是中序遍历的序列,即每个点x与其左右儿子不一定是连续的,所以要用x的左子树中与最右点(最深点,即一定与x相邻)相连的最长距离rdis[lson]。
ldis同理。因为一个点可能一会是左儿子一会是右儿子,所以ldis[lson]也顺便维护。
ldis[x]可以由 左子树中的某条链ldis[lson] 或是 左子树整个与x相连的这条实链+右子树或虚子树中的一条链 更新。
距离更新可能不太方便,直接维护路径上的点数,初始都为1,最后输出-1。
其中 x子树整个与fa[x]相连的实链的长度len[x] 可以直接由 len[lson]+len[rson]+1 更新。
x到最远点的距离mxdis[x]由 max{rdis[lson],ldis[rson],虚子树最大值hp1.top()}(+1)更新。
过x的最长链 = max{rdis[lson]+ldis[rson]+1, 虚子树最长链+左/右子树最长链/虚子树次长链+1},但是ans要算上左右子树、虚子树的ans(再取max)(要整个连通块答案)。

注意hp1[x]中的最长链是要与x相连的,即如果用lson/rson更新则是ldis[rson]/rdis[lson],用直接与其相连的点x更新则是mxdis[x](Access与Link)。

说的比较乱。。尽量在解释清楚了。画画图就能看出来。

//2395ms    31672kb
#include <queue>
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=1e5+5;char IN[MAXIN],*SS=IN,*TT=IN;
inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}
namespace LCT
{#define lson son[x][0]#define rson son[x][1]int sk[N],fa[N],son[N][2],mxdis[N],ldis[N],rdis[N],len[N],ans[N];bool rev[N];struct Heap{std::priority_queue<int> h,d;inline void Delete(int x) {d.push(x);}inline void Insert(int x) {h.push(x);}inline void Fix() {while(!h.empty()&&!d.empty()&&h.top()==d.top()) h.pop(),d.pop();}inline int Top() {Fix(); return h.empty()?0:h.top();}inline int Sec(){Fix(); if(h.empty()) return 0;int tmp=h.top(); h.pop();int ans=Top(); h.push(tmp);return ans;}}hp1[N],hp2[N];inline void Init(int n){for(int i=1; i<=n; ++i) len[i]=ldis[i]=rdis[i]=ans[i]=1;}inline void Rev(int x){rev[x]^=1, std::swap(lson,rson), std::swap(ldis[x],rdis[x]);}inline void PushDown(int x){if(rev[x]) Rev(lson), Rev(rson), rev[x]^=1;}inline bool n_root(int x){return son[fa[x]][0]==x||son[fa[x]][1]==x;}void Update(int x){int ls=lson, rs=rson, vmx=hp1[x].Top();len[x]=len[ls]+len[rs]+1;ldis[x]=std::max(ldis[ls],len[ls]+std::max(ldis[rs],vmx)+1);rdis[x]=std::max(rdis[rs],len[rs]+std::max(rdis[ls],vmx)+1);mxdis[x]=std::max(vmx,std::max(rdis[ls],ldis[rs]))+1;ans[x]=std::max(std::max(hp2[x].Top(),std::max(ans[ls],ans[rs])),std::max(rdis[ls]+ldis[rs]+1,vmx+1+std::max(hp1[x].Sec(),std::max(rdis[ls],ldis[rs]))));}void Rotate(int x){int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;if(n_root(a)) son[b][son[b][1]==a]=x;if(son[x][r]) fa[son[x][r]]=a;fa[a]=x, fa[x]=b, son[a][l]=son[x][r], son[x][r]=a;Update(a);}void Splay(int x){int t=1,a=x; sk[1]=x;while(n_root(a)) sk[++t]=a=fa[a];while(t) PushDown(sk[t--]);while(n_root(x)){if(n_root(a=fa[x])) Rotate(son[a][0]==x^son[fa[a]][0]==a?x:a);Rotate(x);}Update(x);}void Access(int x){for(int pre=0; x; x=fa[pre=x]){Splay(x);hp1[x].Insert(ldis[rson]), hp2[x].Insert(ans[rson]);hp1[x].Delete(ldis[pre]), hp2[x].Delete(ans[pre]);rson=pre, Update(x);}}void Make_root(int x){Access(x), Splay(x), Rev(x);}void Link(int x,int y){Make_root(x), Access(y), Splay(y);fa[x]=y, hp1[y].Insert(mxdis[x]), hp2[y].Insert(ans[x]);Update(y);//y的虚子树变了 别忘更新y啊 }void Cut(int x,int y){Make_root(x), Access(y), Splay(y);son[y][0]=fa[x]=0, Update(y);}void Query(int x){Access(x), Splay(x);printf("%d %d\n",mxdis[x]-1,ans[x]-1);}
}int main()
{int n=read(); LCT::Init(n);for(int i=1; i<n; ++i) LCT::Link(read(),read());for(int m=read(),opt; m--; )if((opt=read())==1) LCT::Link(read(),read());else if(opt==2) LCT::Cut(read(),read());else LCT::Query(read());return 0;
}

考试代码

A

//还没调对,应该是f[0]和f[i]的特判(初值问题),不想改了。。
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=5005,M=1e6+5;int n,A[N],tm[M];
LL P,Q,R,f[N],suf[M],suf2[M];inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}int main()
{
//  freopen("A1.in","r",stdin);
//  freopen("A.out","w",stdout);n=read(); int mx=0;for(int i=1; i<=n; ++i) mx=std::max(mx,A[i]=read());std::sort(A+1,A+1+n);P=read(), Q=read(), R=read();for(int i=1; i<=n; ++i) ++suf2[A[i]];for(int i=1; i<=n; ++i) suf[A[i]]=Q*A[i]*suf2[A[i]];for(int i=mx-1; i; --i) suf[i]+=suf[i+1], suf2[i]+=suf2[i+1];LL res=0;for(int i=1; i<=n; ++i) res+=A[i];res*=Q;f[0]=1e15, f[1]=(A[1]-1)*Q;for(int i=2; i<=n; ++i) f[i]=1e15;for(int i=2; i<=n; ++i){LL ai=A[i];for(int j=i-1; ~j; --j){f[j+1]=std::min(f[j+1],f[j])+(ai>j+1?Q*(ai-j-1):P*(j+1-ai));res=std::min(res,R+f[j+1]+suf[j+2]-Q*(j+1)*suf2[j+2]);}}printf("%I64d\n",res);return 0;
}

B

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=1e6+5;int n,sum[N];
char s[N];bool Check(int k)
{if(k+1==n) return 1;if(!k){for(int i=1; i<=n; ++i) if(sum[i]) return 0;return 1;}for(int i=1; i<=n; ++i){int a=i-1,b=(i+k-1)%n+1; if(!a) a=n;if(sum[n]-sum[i+k]==0 && s[a]!=s[b]) return 1;}return 0;
}
void Solve()
{n=strlen(s+1); sum[1]=0;for(int i=2; i<=n; ++i)sum[i]=sum[i-1]+(s[i]==s[i-1]);
//  sum[n+1]=sum[n]+(s[n]==s[1]);
//  for(int i=n+2; i<=n<<1; ++i) sum[i]=sum[i-1]+(s[i-n]==s[i-n-1]);
//  for(int i=1; i<=n; ++i) printf("%d:%d\n",i,sum[i]);for(int k=0; k<n; ++k) putchar(Check(k)+'0');putchar('\n');
}int main()
{freopen("b2.in","r",stdin);freopen("b.out","w",stdout);int Cs=1;while(~scanf("%s",s+1))printf("Case %d:",Cs++), Solve();return 0;
}

C

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 400000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5,M=4e5+5;int n,Enum,H[N],nxt[M],to[M],len[M],V,D;
bool ban[5003][5003];
char IN[MAXIN],*SS=IN,*TT=IN;inline int read()
{int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now;
}
inline void AddEdge(int u,int v)
{if(ban[u][v]) {ban[u][v]=ban[v][u]=0; return;}to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum;
}
void DFS(int x,int f,int d)
{if(d>D) D=d, V=x;for(int i=H[x],v; i; i=nxt[i])if((v=to[i])!=f && !ban[x][v]) DFS(v,x,d+1);
}int main()
{
//  freopen("c2.in","r",stdin);
//  freopen("my.out","w",stdout);n=read();for(int i=1; i<n; ++i) AddEdge(read(),read());for(int Q=read(),u,v,opt; Q--; )if((opt=read())==1) AddEdge(read(),read());else if(opt==2) u=read(),v=read(),ban[u][v]=ban[v][u]=1;else{V=u=read();D=0, DFS(u,u,0), printf("%d ",D), D=0, DFS(V,V,0), printf("%d\n",D);}return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/9431266.html

8.6 正睿暑期集训营 Day3相关推荐

  1. 8.8 正睿暑期集训营 Day5

    目录 2018.8.8 正睿暑期集训营 Day5 总结 A 友谊巨轮(线段树 动态开点) B 璀璨光滑 C 构解巨树 考试代码 A B C 2018.8.8 正睿暑期集训营 Day5 时间:3.5h( ...

  2. 8.10 正睿暑期集训营 Day7

    目录 2018.8.10 正睿暑期集训营 Day7 总结 A 花园(思路) B 归来(Tarjan 拓扑) C 机场(凸函数 点分治) 考试代码 A B C 2018.8.10 正睿暑期集训营 Day ...

  3. 7.30 正睿暑期集训营 A班训练赛

    目录 2018.7.30 正睿暑期集训营 A班训练赛 T1 A.蔡老板分果子(Hash) T2 B.蔡老板送外卖(并查集 最小生成树) T3 C.蔡老板学数学(DP NTT) 考试代码 T2 T3 2 ...

  4. 【2019正睿金华集训】0803总结

    今天是R姓大佬讲解的(简单?)数论. 果然数论还是那么的毒瘤,前面还好,讲到类欧就挂机了.讲到二次剩余,woc什么鬼东西,直接挂机.讲到莫比乌斯反演又挂机了,直到看完一篇有关数论函数的博客才上线. 数 ...

  5. 2019金华正睿集训总结

    emmm-蒟蒻第一次出来集训,也是2019年noip(现在应该叫csp的说)前最后一次外出集训- 感觉压力好大啊-毕竟才学了不到一年啊- 但不管怎样,接下来几天要好好加油啊! DAY1 仅自己用的链接 ...

  6. 中南大学计算机学院盛羽,中南大学、新疆大学ACM暑期联合集训营顺利开营

    本网讯 7月21日上午,中南大学.新疆大学ACM暑期联合集训营在校本部科技楼实验室顺利开营.由新疆大学软件学院副院长王新辉作为领队的15名新大师生与中南大学ACM集训队学生共同参加了开营仪式,计算机学 ...

  7. [2019 牛客CSP-S提高组赛前集训营4题解] 复读数组(数论)+ 路径计数机(数上DP)+ 排列计数机(线段树+二项式定理)

    文章目录 T1:复读数组 题目 题解 代码实现 T2:路径计数机 题目 题解 代码实现 T3:排列计数机 题目 题解 CODE T1:复读数组 题目 有一个长为n×k的数组,它是由长为n的数组A1,A ...

  8. 三层架构学习的困难_“网工起航计划”3天集训营 带你了解大型企业网络架构设计!...

    点击蓝字 关注我们 网工起航计划 3天集训营 带你了解大型企业网络架构设计 开营时间:8月26日晚8点 DAY1:企业园区网二层架构冗余设计实战  时间:8月26日20:00-21:30 1.网络通信 ...

  9. 【解题报告】2021牛客寒假算法基础集训营4

    [解题报告]2021牛客寒假算法基础集训营4 前面的话 A :九峰与签到题 | 模拟 (签到题) B: 武辰延的字符串 | exKMP D :温澈滢的狗狗 | 二分 E: 九峰与子序列 | d p d ...

最新文章

  1. BZOJ 3626: [LNOI2014]LCA
  2. lintcode:排颜色 II
  3. Vue2 使用Volar 报错:<template v-for> key should be placed on the <template> tag
  4. Excel Access 新建空白文档/打开已有文档 提示内存或磁盘空间不足的解决方法--验证...
  5. php怎么实现显示gif图片,利用PHP怎么对gif图片进行判断
  6. 一字之差——手机中的“拼”音输入法和“注”音输入法
  7. 电脑软件:推荐一款本地文档搜索神器,赶快下载试试吧!
  8. PCWorld测评的2012版世界级杀毒软件
  9. STM32采集电流互感器(电流互感器模块)数据
  10. bat怎么发起网络请求_批处理命令教程之网络入侵
  11. Android audio 三 AudioRecord 分析下
  12. 【mac 环境】邮箱密码修改后,foxmail无法正常接收邮件
  13. flash的Socket连接,服务端用没有平台限制
  14. 理解 Android Battery 信息
  15. GNU m4 教程[转]
  16. Unity 之 发布 Mac 报错 il2cppcore.dll did not run propertly
  17. steam 创客教育
  18. “Word在试图打开文件时遇到错误。请尝试下列方法:* 检查文档或驱动器的文件权限。* 确保有足够的内存和磁盘空间。* 用文件恢复转换器打开文件。”问题!...
  19. Altium Designer--如何快速查看PCB网络布线
  20. 来自千里之外祖国的关爱

热门文章

  1. 全双工串口、半双工串口总线及其转换
  2. 盗墓笔记android,盗墓笔记安卓手游-盗墓笔记1.3.0下载_飞翔下载
  3. Iterative Pruning
  4. 蛇行矩阵(详细题解+注释)
  5. linux上存储和读取bmp图像文件
  6. 硬盘常用分区格式与最大支持
  7. 谷歌浏览器安装Postman插件(2020亲测)
  8. 长三角农业一体化,从“大闸蟹联盟”开始
  9. 如何将 MacBook 连接到电视,怎么把苹果电脑连接到电视机
  10. 小米4拍照上传时候,上传的图片size为零