\(\color{white}{\mathbb{深秋总有廖落处,雁归每是菊败时,名之以:残菊}}\)


这场比赛几乎全场都在打暴力,几乎人均切掉的 \(t1\) 没有想到双指针,\(t3\) 的暴力也没记忆化而太过暴力


A. a

很容易想到同时枚举两行,然后算列的贡献

考场上只想到用数状数组维护,但是很显然 \(down\) 和 \(up\) 两条线之间区域的边界是单调的,双指针维护即可


B.b

考虑对于每个 \(i\) 计算 \(i|gcd\) 的方案数,设每一组是 \(i\) 的倍数的数有 \(cnt_j\) 个,答案为 \(\prod (cnt_j+1)-1\)

但是此时每个 \(i\) 保存的是其所有倍数的值之和,那么考虑倒序枚举所有数,其实大于当前数的所有数已经还原成 \(i=gcd\) 的值,那么用当前数的值减去所有倍数的值即可


C.c

一开始没看见去重后是棵树……

首先每条边都有多种候选颜色,但只保留三种即可,即和上一个不重,和下一个不重

考虑点分治,从分治中心开始 \(dp\),设 \(f[i][0/1/2][0/1/2]\) 表示从中心到第 \(i\) 个点,路径上第一条边的颜色为第几种,最后一条边的颜色是第几种的最大价值

然后写棵点分树把询问挂在点分树上的 \(lca\) 就好了

代码实现
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=1e6+5;
int hd[maxn],cnt,from[maxn],las[maxn],f[maxn][5][5],n,m,q,xx[maxn],yy[maxn],fa[maxn],fa1[maxn],dep[maxn],siz[maxn],rt,maxx[maxn],x,y,w,sum,sta[maxn],tp;
bool del[maxn];
vector<pair<int,int> >has[maxn];
map<pair<int,int>,int>ans,mp;
int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-48;
ch=getchar();
}
return x*f;
}
struct Edge{
int nxt,to,val[4];
int numval;
}edge[maxm];
void add(int u,int v,int w){
edge[++cnt].nxt=hd[u];
edge[cnt].to=v;
edge[cnt].val[++edge[cnt].numval]=w;
hd[u]=cnt;
return ;
}
void dfs_w(int u,int father){
siz[u]=1;
maxx[u]=0;
for(int i=hd[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==father||del[v])continue;
dfs_w(v,u);
siz[u]+=siz[v];
maxx[u]=max(maxx[u],siz[v]);
}
maxx[u]=max(maxx[u],sum-siz[u]);
if(maxx[u]<maxx[rt])rt=u;
return ;
}
void dfs_dis(int u,int father,int last,int num){
// cout<<u<<" "<<father<<" "<<last<<" "<<num<<endl;
sta[++tp]=u;
from[u]=num;
las[u]=last;
for(int i=hd[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==father||del[v])continue;
for(int j=1;j<=edge[num].numval;j++){
for(int k=1;k<=edge[last].numval;k++){
for(int p=1;p<=edge[i].numval;p++){
f[v][j][p]=max(f[v][j][p],f[u][j][k]+(edge[last].val[k]!=edge[i].val[p]));
} }
}
dfs_dis(v,u,i,num);
}
return ;
}
void calc(int u){
// cout<<u<<endl;
tp=0;
for(int i=hd[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(del[v])continue;
for(int j=1;j<=edge[i].numval;j++)f[v][j][j]=1;
dfs_dis(v,u,i,i);
} for(int i=0;i<has[u].size();i++){
int x=has[u][i].first,y=has[u][i].second,mx=0;
// if(u==4)cout<<x<<" "<<y<<endl;
if(y==u)swap(x,y);
if(x==u){
for(int j=1;j<=edge[from[y]].numval;j++){
for(int k=1;k<=edge[las[y]].numval;k++){
mx=max(mx,f[y][j][k]);
}
}
ans[has[u][i]]=mx;
continue;
}
for(int j=1;j<=edge[from[x]].numval;j++){
for(int k=1;k<=edge[from[y]].numval;k++){
for(int l=1;l<=edge[las[x]].numval;l++){
for(int r=1;r<=edge[las[y]].numval;r++){
mx=max(mx,f[x][j][l]+f[y][k][r]-(edge[from[x]].val[j]==edge[from[y]].val[k]));
}
}
}
}
ans[has[u][i]]=mx;
}
// for(int i=1;i<=tp;i++)cout<<sta[i]<<" ";
// cout<<endl;
for(int i=1;i<=tp;i++){
for(int j=1;j<=3;j++){
for(int k=1;k<=3;k++){
// if(u==4)cout<<sta[i]<<" "<<edge[from[sta[i]]].val[j]<<" "<<edge[las[sta[i]]].val[k]<<" "<<f[sta[i]][j][k]<<endl;
f[sta[i]][j][k]=0;
}
}
}
return ;
}
void solve(int u){
// cout<<" "<<u<<endl;
del[u]=true;
calc(u);
for(int i=hd[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(del[v])continue;
rt=0;
maxx[rt]=sum=siz[v];
dfs_w(v,u);
solve(rt);
}
return ;
}
void solve0(int u){
// cout<<u<<endl;
del[u]=true;
// calc(u);
for(int i=hd[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(del[v])continue;
rt=0;
maxx[rt]=sum=siz[v];
dfs_w(v,u);
fa1[rt]=u;
dep[rt]=dep[u]+1;
solve0(rt);
}
return ;
}
int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
while(dep[x]!=dep[y]){
x=fa1[x];
}
while(x!=y){
x=fa1[x];
y=fa1[y];
}
return x;
}
int main(){
// freopen("c0_1.in","r",stdin);
n=read();
m=read();
// memset(f,-1,sizeof f);
for(int i=1;i<=m;i++){
x=read();
y=read();
w=read();
if(mp.find(make_pair(x,y))==mp.end())mp[make_pair(x,y)]=mp[make_pair(y,x)]=cnt+1,add(x,y,w),add(y,x,w);
else{
int id=mp[make_pair(x,y)];
if(edge[id].numval<=2&&edge[id].val[1]!=w&&edge[id].val[2]!=w){
edge[id].val[++edge[id].numval]=w;
}
id++;
if(edge[id].numval<=2&&edge[id].val[1]!=w&&edge[id].val[2]!=w){
edge[id].val[++edge[id].numval]=w;
}
}
}
// for(int i=1;i<=cnt;i+=2){
// cout<<edge[i].to<<" "<<edge[i+1].to<<" "<<edge[i].val[1]<<" "<<edge[i].val[2]<<" "<<edge[i].val[3]<<endl;
// }
maxx[rt]=sum=n;
dfs_w(1,0);
// cout<<"ppp "<<rt<<endl;
solve0(rt);
// for(int i=1;i<=n;i++){
// cout<<fa1[i]<<" ";
// }
q=read();
for(int i=1;i<=q;i++){
xx[i]=read();
yy[i]=read();
// cout<<" "<<lca(xx[i],yy[i])<<endl;
has[lca(xx[i],yy[i])].push_back(make_pair(xx[i],yy[i]));
}
memset(del,0,sizeof del);
memset(maxx,0,sizeof maxx);
memset(siz,0,sizeof siz);
rt=0;
// cout<<"hhh"<<endl;
maxx[rt]=sum=n;
dfs_w(1,0);
solve(rt);
for(int i=1;i<=q;i++){
printf("%d\n",ans[make_pair(xx[i],yy[i])]);
}
return 0;
}

\(\color{white}{\mathbb{不是花中偏爱菊,此花开尽更无花。}}\)

noip模拟38的更多相关文章

  1. Noip模拟38 2021.8.13

    T1 a 跟入阵曲很像,但是忘记入阵曲这题的思路是什么了 这里再提一下,入阵曲是子矩阵和是$k$的倍数,这道题目是子矩阵和是在一段区间内$[L,R]$ 因为这道题$n$特别小,$m$较大,考虑复杂度为 ...

  2. 2021.8.13考试总结[NOIP模拟38]

    T1 a 入阵曲.枚举矩形上下界,之后从左到右扫一遍.用树状数组维护前缀和加特判可以$A$,更保险要脸的做法是双指针扫,因为前缀和单调不减. $code:$ 1 #include<bits/st ...

  3. NOIP模拟 38

    liu_runda的题! 错过辽QAQ T1虽然没用题解的损益法,但是用高精%还能过.. 没想到敲完就过编译了,还以为要调一天呢 高精度的阴影没了- T2的思路很巧妙 首先一个区间最多有一种颜色占一半 ...

  4. NOIP 模拟 $38\; \rm c$

    题解 \(by\;zj\varphi\) 发现就是一棵树,但每条边都有多种不同的颜色,其实只需要保留随便三种颜色即可. 直接点分治,将询问离线,分成一端为重心,和两端都不为重心的情况. 每次只关心经过 ...

  5. NOIP 模拟 $38\; \rm b$

    题解 \(by\;zj\varphi\) 考虑转化问题,将计算最大公约数换为枚举最大公约数. 设 \(sum_i\) 为最大公约数为 \(i\) 的方案数,可以容斥求解,\(sum_i=f_i-\su ...

  6. NOIP 模拟 $38\; \rm a$

    题解 \(by\;zj\varphi\) 压行. 枚举两行,将中间的行压成一行,然后直接前缀和加二分. 注意边界细节问题. Code #include<bits/stdc++.h> #de ...

  7. NOIP模拟38:b

      这是T2.   一个容斥(其实也可以欧拉反演做,但是我不会).   首先开一个桶,记录第i行的j有多少个.   然后枚举1-\(maxn\),枚举他的值域内的倍数,记录倍数在第i行有多少个,将个数 ...

  8. NOIP模拟38:a

      这是T1.   考场上思路与正解就差个前缀,打的线段树,因为其巨大常数快乐挂掉......   正解复杂度是\(O(n^2m)\),其实再挂个\(log\)也能过,但是需要用常数极其优秀的树状数组 ...

  9. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

随机推荐

  1. k8s强制删除资源

    一般强制删除 kubernetes 的资源: kubectl delete <resource> <resourename> --grace-period=0 --force ...

  2. Windows影子用户创建与3389连接

    #当获得一条shell后,可以创建一个影子用户,通过影子用户可以行驶正常用户的所有权限与功能,并且只可在注册表中被检测出来---(应急响应注册表很重要) 1.首先需要拥有权限创建一个Administr ...

  3. AMD CMD commonJS es6

    看到很多人傻傻的分不清楚 AMD.CMD . commonJS . es6的区别,实际上这跟这几年前段技术的发展有很大的关系. 实际上这是JavaScript的模块化思想演进的一个过程. 最开始的时候 ...

  4. AWD比赛组织指南

    目录 题目构建 平台构建 后端部署流程 前端展示 批量启动 check 题目构建 赛题全部使用docker部署,需准备check脚本和镜像 镜像构建注意事项 1.注意web目录权限 2.注意服务是否自 ...

  5. NOIP 模拟 $22\; \rm d$

    题解 很好的贪心题 考虑去掉的矩形一定是几个 \(a\) 最小的,几个 \(b\) 最小的,枚举去掉几个 \(a\),剩下的去掉 \(b\) 先对 \(a\) 排序,用小根堆维护 \(b\) ,记录哪 ...

  6. NOIP 模拟 10 考试总结

    T1 一道很妙的题,打暴力分也很多,但是考试的时候忘开 long long 了. 题解 T2 一道挺水的题,不过...(打挂了) 题解 T3 此题甚妙,转化真多,不过对思维是一个非常大的扩展 题解 考 ...

  7. 题解 [NOIP2017 提高组]宝藏

    传送门 这是蓝书上状压的例题啊,怎么会出现在模拟赛里 不过就算原题我也没把握写对 核心思路: 先令\(dp[s]\)为当前状态为\(s\)时的总花费最小值,\(cnt[s][i]\)为这个方案中由根节 ...

  8. 公司新来了一个质量工程师,说团队要保证 0 error,0 warning

    摘要:静态代码检查又称为静态程序分析,是指在不运行计算机程序的条件下,进行程序分析的方法. 本文分享自华为云社区<公司新来了一个质量工程师,说团队要保证 0 error,0 warning> ...

  9. JavaScript之BOM和DOM及其兼容操作详细总结

    BOM(浏览器对象模型) 所有浏览器都支持window对象,他表示浏览器窗口. 所有js全局对象,函数,变量均自动成为window对象的成员. 全局变量是window对象的属性. 全局函数是windo ...

  10. .net core api 对于FromBody的参数验证

    前言 在framework的mvc中,经常会使用 Model.State . ModelState.IsValid 配合着特性进行参数验证,通过这种方式可以降低controller的复杂度,使用方便. ...