\(\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. 项目去O实践

    现状(自下而上) 1.Oracle数据库,表,序列,存储过程,视图 2.ibatis框架,映射xml中的sql语句 3.应用中通过指定字符串的形式获取查询结果   目标 1.置换数据库为PG数据库,迁 ...

  2. 离线安装zadig

    官网:https://koderover.com/ 官方给的离线安装问题有些问题,这里记录下自己离线安装的一些过程. 整体安装思路: 根据官方给出的helm安装方式以及离线安装方式结合而来. 通过官方 ...

  3. Activiti7 结束/终止流程

    1.  结束/终止 正在运行的流程实例 思路:跟回退一样的思路一样,直接从当前节点跳到结束节点(EndEvent) /** * 结束任务 * @param taskId 当前任务ID */ publi ...

  4. Java面向对象02——回顾方法(定义、调用)及加深

    方法的定义  package oop.demon01; ​ //Demon01 类 public class Demon01 {          //main 方法     public stati ...

  5. C函数调用(2)

    1 //函数调用 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <math.h> 6 //根据传入 ...

  6. Windows协议 LDAP篇 - 组&OU

    LDAP搜索 LDAP查找 位操作 以userAccountControl为例,CN=User-Account-Control,CN=Schema,CN=Configuration,DC=muxue, ...

  7. Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

    Spring Cloud Stream 简介 在微服务的开发过程中,可能会经常用到消息中间件,通过消息中间件在服务与服务之间传递消息,不管你使用的是哪款消息中间件,比如RabbitMQ.Kafka和R ...

  8. uname指令

    以下是一台Solaris 10服务器的配置信息, bash-3.00$ uname -a SunOS NOP2-HWXX 5.10 Generic_138888-03 sun4u sparc SUNW ...

  9. 安鸾CTF Writeup wordpress 01

    题目一: wordpress 01 URL:http://whalwl.site:8041/ wordpress 站思路就是先用wpscan 进行扫描检测一遍. wpscan 使用方法可以参考两篇文章 ...

  10. 【Vulnhub】DC-2靶机

    Vulnhub DC-2 靶机 信息搜集 访问web端发现访问不了,可以观察到相应的URL为域名而不是IP,需要在hosts文件种添加一条DNS记录. host位置:C:\Windows\System ...