20230925 比赛总结

news/2024/7/23 11:05:55 标签: 算法

反思

A

感觉有点降智,一眼 m a n a c h e r manacher manacher,但很久才想到可以二分,然后就转化成了一个区间最大值问题

B

感觉有点弱智的题,题目不难,一开始算复杂度的时候认为 [ 1.5 − 3 ] ∗ 1 0 8 [1.5-3]*10^8 [1.53]108 冲不过 1 s 1s 1s,事实上开了 O 2 O2 O2 只要 800 m s 800ms 800ms

C

乱搞大爱!!!
但忘记 l o n g    l o n g × l o n g    l o n g long\;long \times long\; long longlong×longlong 会爆!!!

题解

比赛链接

A

感觉 m a n a c h e r manacher manacher 挺显然的,因为是回文
然后的询问二分想了很久才想到,深感自己菜的本质,写代码时一些细节也调了很久

B

没什么好说的,直接 d p dp dp,压一下状态开冲!感觉人傻常数大,可能不加那个小剪枝就被卡常了

C

我是乱搞人!!!直接 100 p t s 100pts 100pts,我惊了!
正解是维护凸包,但我不会,先不补了

D

感觉是一道挺像暴力的数据结构
注意到 k k k 很小,所以可以估计到 k k k 只是用来卡常用的
所以我们考虑一组询问可以在 O ( n l o g n ) − O ( n l o g 2 n ) O(nlogn)-O(nlog^2n) O(nlogn)O(nlog2n) 的时间复杂度内求解
考虑 m e x mex mex 具有可二分性,所以先二分
对于 m i d > 1 mid>1 mid>1 的情况,考虑找到一条最短的路径覆盖 0 0 0 m i d − 1 mid-1 mid1 中所有的点,如果不能,就不行,然后我们考虑从两个端点往两边拓展,然后塞到 t r i e trie trie 树上查询有没有异或和在 l − r l-r lr 之间的数,这个是容易实现的
对于 m i d = 1 mid=1 mid=1 的情况,我们即要找到一条路径的端点在以 0 0 0 为根的两棵子树中,这个也是可以用 t r i e trie trie 树维护的
时间复杂度 O ( k n l o g 2 n ) O(knlog^2n) O(knlog2n)(听说 l o g 2 log^2 log2 被卡了,不过没事, n f l s nfls nfls 不会重测代码

#include <bits/stdc++.h>
using namespace std;
const int N=100100;
int n,q,l,r,dis[N];
int depth[N],up[N][20];
int e[N<<1],w[N<<1],ne[N<<1],h[N],idx;
int st[N],ed[N],lim;
int ox[N],cnt;
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
int get_lca(int x,int y){
    if(depth[x]>depth[y]) swap(x,y);
    for(int i=18;i>=0;i--) if(depth[up[y][i]]>=depth[x]) y=up[y][i];
    if(x==y) return x;
    for(int i=18;i>=0;i--) if(up[x][i]!=up[y][i]) x=up[x][i],y=up[y][i];
    return up[x][0];
}
int get_dist(int x,int y){ return depth[x]+depth[y]-2*depth[get_lca(x,y)];}
void insert(int u,int fa,int xo){
	ox[++cnt]=xo;
	for(int i=h[u];~i;i=ne[i]) if(e[i]!=fa) insert(e[i],u,xo^w[i]);
}
struct Trie{
	int idx,tr[N*31][2],cnt[N*31];
	void clear(){
        for(int i=0;i<=idx;i++) tr[i][0]=tr[i][1]=cnt[i]=0;
        idx=0;
    }
	void insert(int v){
		int p=0;
		for(int i=30;i>=0;i--){
			int c=v>>i&1;
			if(!tr[p][c]) tr[p][c]=++idx;
			p=tr[p][c],cnt[p]++;
		}
	}
	int query(int v,int lim){
		if(lim<0) return 0;
		int p=0,res=0;
		for(int i=30;i>=0;i--){
			int c1=lim>>i&1,c2=v>>i&1;
			if(c1){
                res+=cnt[tr[p][c2]];
                if(!tr[p][c2^1]) return res;
                p=tr[p][c2^1];
            }
			else{
                if(!tr[p][c2]) return res;
                p=tr[p][c2];
            }
		}
		return res+cnt[p];
	}
}trie;
bool check1(int mid){//mid>1的情况
	if(mid>lim) return false;
	int S=st[mid],E=ed[mid];
	int d=get_dist(S,E),fas,fae;
	for(int i=h[S];~i;i=ne[i]) if(get_dist(e[i],E)==d-1) fas=e[i];
	for(int i=h[E];~i;i=ne[i]) if(get_dist(e[i],S)==d-1) fae=e[i];
	cnt=0,insert(S,fas,0);
	trie.clear();
	for(int i=1;i<=cnt;i++) trie.insert(ox[i]);
	cnt=0,insert(E,fae,dis[S]^dis[E]);
	for(int i=1;i<=cnt;i++) if(trie.query(ox[i],r)-trie.query(ox[i],l-1)) return true;
	return false;
}
bool check2(){
	trie.clear();
	for(int i=h[0];~i;i=ne[i]){
		cnt=0,insert(e[i],0,w[i]);
		for(int j=1;j<=cnt;j++) if(trie.query(ox[j],r)-trie.query(ox[j],l-1)) return true;
		for(int j=1;j<=cnt;j++) trie.insert(ox[j]);
	}
	return false;
}
bool insert_node(int x){
	int d1=get_dist(x,st[x-1]),d2=get_dist(x,ed[x-1]),d3=get_dist(st[x-1],ed[x-1]);
	if(d1+d2==d3) return true;
	if(d1+d3==d2){ st[x]=x;return true;}
	if(d2+d3==d1){ ed[x]=x;return true;}
	return false;
}
void dfs(int u,int fa){
    depth[u]=depth[fa]+1;
	for(int i=h[u];~i;i=ne[i]) if(e[i]!=fa) dis[e[i]]=dis[u]^w[i],up[e[i]][0]=u,dfs(e[i],u);
}
void add(int x,int y,int z){ e[idx]=y,w[idx]=z,ne[idx]=h[x],h[x]=idx++;}
int main(){
    freopen("nim.in","r",stdin);
    freopen("nim.out","w",stdout);
	n=read(),q=read();
	memset(h,-1,sizeof(h));
	for(int i=1;i<n;i++){
		int x=read(),y=read(),z=read();
		add(x,y,z),add(y,x,z);
	}
	dfs(0,0);
    for(int j=1;j<=18;j++) for(int i=1;i<=n;i++) up[i][j]=up[up[i][j-1]][j-1];
	st[0]=ed[0]=0,st[1]=0,ed[1]=1;
	for(int i=2;i<=n;i++){
        st[i]=st[i-1],ed[i]=ed[i-1];
		if(!insert_node(i)) break;
		lim=i;
	}
	while(q--){
		l=read(),r=read();
		int lb=1,rb=n+1;
		while(lb<rb-1){
			int mid=(lb+rb)>>1;
            check1(mid-1)?lb=mid:rb=mid;
		}
        if(lb==1){
            if(check2()) puts("1");
            else puts("0");
        }
        else printf("%d\n",lb);
	}
	fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC));
	return 0;
}


http://www.niftyadmin.cn/n/5049178.html

相关文章

DAZ To UMA⭐三.导入Blender的配置, 及Blender快捷键

文章目录 🟥 Blender快捷键1️⃣ 3D视图快捷键2️⃣ 视角快捷键3️⃣ 编辑快捷键4️⃣ 对物体的操作🟧 Blender导入FBX的配置🟩 设置脸部骨骼大小1️⃣ 切换视角2️⃣ 缩小脸部骨骼3️⃣ 本节效果预览🟦 设置眼角膜透明度🟥 Blender快捷键 1️⃣ 3D视图快捷键 快捷键…

android 默认开启谷歌定位精准度

摘要&#xff1a;本文主要提供一种默认开启谷歌定位精准度开关的方案。通过调试时打开/关闭开关对比SettingsProvider的数据变化&#xff0c;在开机收到ACTION_BOOT_COMPLETED广播后&#xff0c;主动修改并填充数据&#xff0c;实现默认打开的需求。 在设置中实现方案 因为设…

登录业务实现 - token登录鉴权

登录业务实现&#xff1a; 登录成功/失败实现 -> pinia管理用户数据及数据持久化 -> 不同登录状态的模板适配 -> 请求拦截器携带token&#xff08;登录鉴权&#xff09; -> 退出登录实现 -> token失效&#xff08;401响应拦截&#xff09; 1. 登录成…

C#中的(++)和(--)运算符

目录 背景: 的前加 效果展示:​ 的后加 效果展示 :​ 总结: 背景: 自增和自减运算符存在于C/C/C#/Java等高级语言中&#xff0c;它的作用是在运算结束前(前置自增自减运算符 )或后(后置自增自减运算符 )将 变量的值加(或减)1。 在C#中&#xff0c;和--是自增和自减运…

前后台分离开发 YAPI平台 前端工程化之Vue-cli

目录 YAPI介绍前端工程化之Vue-cli前端工程化简介前端工程化入门——Vue-cli环境准备Vue项目简介创建Vue项目vue项目目录结构介绍vue项目运行方法 Vue项目开发流程 前后台混合开发这种开发模式有如下缺点&#xff1a; 沟通成本高&#xff1a;后台人员发现前端有问题&#xff0…

L1-032 Left-pad C++解法

一、题目再现 根据新浪微博上的消息&#xff0c;有一位开发者不满NPM&#xff08;Node Package Manager&#xff09;的做法&#xff0c;收回了自己的开源代码&#xff0c;其中包括一个叫left-pad的模块&#xff0c;就是这个模块把javascript里面的React/Babel干瘫痪了。这是个…

python安全工具开发笔记(五)——python数据库编程

一、Python DB API 在没有Python DB API之前&#xff1a; 有Python DB API之后&#xff1a; Python DB API包含内容 Python DB API访问数据库流程 二、Python Mysql开发环境 三、Python 数据库编程实例 数据库连接对象connection 连接对象&#xff1a;建立Python客户端…

使用 Ruby 语言来解析开放文档格式 OOXML 文件

在这篇文章中&#xff0c;我们将了解一个开发团队如何解决他们在应用程序中解析数据时遇到的问题。 为了测试 ONLYOFFICE 文档编辑器&#xff0c;我们用Ruby语言开发编写了个docx、xlsx、pptx文件解析器程序&#xff0c;它是免费开源的&#xff0c;被我们放在GitHub和RubyGems…