数据结构测试1 on 2019.9.24

T1 union

一开始我被这个题目带进去了,以为真的是并查集,但实际上此题与并查集毫无半毛钱关系。

其实我们可以先离线建好所有的图,然后把建边的时间作为他们的边权。因为两个点什么时候联通取决于它们路径上的点最晚的链接时间,也就是最大边权。而题目明摆了是一棵树,所有考虑树剖维护边权和查询最大值。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
struct node{
    int nxt,to,val;
}edge[maxn*3];
int head[maxn],cnt;
int n,m,x,y;
int w[maxn],dep[maxn],fa[maxn],size[maxn],son[maxn];
void add(int x,int y,int v){
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;
    edge[cnt].val=v;
    head[x]=cnt;
}
void dfs1(int x,int f){
    size[x]=1;
    fa[x]=f;
    dep[x]=dep[f]+1;
    int maxson=-1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v==fa[x]) continue;
        w[v]=edge[i].val;
        dfs1(v,x);
        size[x]+=size[v];
        if(size[v]>maxson){
            maxson=size[v];
            son[x]=v;
        }
    }
}
int top[maxn],id[maxn],in;
int val[maxn];
void dfs2(int x,int topf){
    top[x]=topf;
    id[x]=++in;
    val[id[x]]=w[x];
    if(!son[x]) return;
    dfs2(son[x],topf);
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v==fa[x]||v==son[x]) continue;
        dfs2(v,v);
    }
}
struct node2{
    int l,r,mx;
}tree[maxn*4];
void build(int now,int l,int r){
    tree[now].l=l,tree[now].r=r;
    if(l==r){
        tree[now].mx=val[l];
        return;
    }
    int mid=(l+r)>>1;
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    tree[now].mx=max(tree[now<<1].mx,tree[now<<1|1].mx);
}
int query(int now,int l,int r){
    if(tree[now].l>=l&&tree[now].r<=r) return tree[now].mx;
    int ans=0;
    int mid=(tree[now].l+tree[now].r)>>1;
    if(l<=mid) ans=max(ans,query(now<<1,l,r));
    if(r>mid) ans=max(ans,query(now<<1|1,l,r));
    return ans;
}
int link(int x,int y){
    if(x==y) return 0;
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans=max(ans,query(1,id[top[x]],id[x]));
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    ans=max(ans,query(1,id[y]+1,id[x]));
    return ans;
}
int main(){
    freopen("union.in","r",stdin);
    freopen("union.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        add(x,y,i);add(y,x,i);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        printf("%d\n",link(x,y));
    }
    return 0;
} 

T2 lcs

题目非常显然,但是1e5的数据范围肯定没法像原来那样n方的去dp,于是我们必须将它用某种数据结构维护来优化为log的复杂度,显然想到树状数组。其实树状数组求lcs简单好写,跑的还非常快。

树状数组都知道可以求lis,但怎么把它转化为求lcs的问题呢?肯定是离散化啊!先将第一个序列离散为一个单调递增的序列,然后根据第一个序列上每一位的哈希值又离散化第二个序列,这个时候我们发现,由于第一个序列已经是有序的了,我们将第二个序列离散化后最长单调递增的序列那么肯定就是lcs了。

//离散化,转化为树状数组求lis的问题
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
int dp[maxn];
int n;
int a[maxn];
int c[maxn];
int b[maxn];
int lis[maxn];
int lis1[maxn];
int lowbit(int x){
    return x&(-x);
}
void modify(int x,int v){
    while(x<=n){
        c[x]=max(c[x],v);
        x+=lowbit(x);
    }
}
int query(int x){
    int ans=0;
    while(x){
        ans=max(ans,c[x]);
        x-=lowbit(x);
    }
    return ans;
}
int ans;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        lis[a[i]]=i;//映射,离散化
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&b[i]);
        lis1[i]=lis[b[i]];
    }
    for(int i=1;i<=n;i++){
        dp[i]=query(lis1[i])+1;
        modify(lis1[i],dp[i]);
    }
    for(int i=1;i<=n;i++) ans=max(dp[i],ans);
    printf("%d\n",ans);
    return 0;
} 

T3 files

stl+模拟文件操作即可

原文地址:https://www.cnblogs.com/LJB666/p/11614625.html

时间: 2024-08-30 14:31:16

数据结构测试1 on 2019.9.24的相关文章

数据结构测试2 on 2019.9.25

又是一天的数据结构,但今天直接爆炸,1题和3题都写挂了200->0. T1 abnormal 一开始想的是线段树,但是自己感觉维护不来,果断放弃线段树.这时又想到离线的莫队做法,本以为这道题稳了,结果最后还是打炸了.题面意思都搞错了,真的是个傻逼. 这道题对于莫队来讲就是最简单的莫队,用一个数组cnt来维护每个魅力值的出现次数即可,但注意在统计出现次数的时候,还是要加注意,因为题目中定义的不正常团伙是只能出现2次,所以少于两次的和超过两次的都要累加他们的贡献.需要小小的特判. 代码如下: #in

网络流测试-2019.3.24

网络流专题测试-2019.03.24 24号的考试了,但是一直忘了写,今天来补一补. defuze:http://hzwer.com/6009.html 不想写题面了,直接说怎么做吧. 其实这道题可以直接用最普通的费用流来做,找增广路时把spfa的比较函数改改就行了,但是我没想到. 可以对概率取对数,转成加法再做,就非常简单了. 注意:找增广路时设置一个精度,如果两条路径的差小于精度,就不进行松弛.否则可能会在几条费用极其相似的道路上反复增光导致超时. 1 # include <cstdio>

2019.7.24 校内测试 分析+题解

T1 地雷 题目很简单呢,就是求哪个数只出现了一次就可以了哦~ 我一开始的想法是桶排(这也是最单纯最简单的想法吧~),但是空间开 232 肯定会炸的,而且时间好像也会炸掉. 然后左边的 ych 大佬小声说了一句:“得换个算法.” 嗯,确实要换个算法,然后我就觉得新算法一定是不用开数组,直接输完数据就能出答案的那种! 然后不知道怎么就想到了 zhx 讲博弈论的时候输入的同时将 ……(一些稀奇古怪的东西) 异或起来就是答案,这不正好跟我理想的新算法很像嘛? 异或异或?咦,又想到了六月底那次考试有个叫

精准测试白皮书-2019最新版

精准测试白皮书 精准测试诞生的背景 现代社会是建立在各种以计算机为基石的软件技术基础之上的.随着日新月异的需求变化,软件系统越来越复杂.很多人觉得软件开发才是重要环节,但实际上,无法对大型软件进行有效的质量把控,就无法真正构建与维护大型软件.--系统中任何一个错误都可能导致整个系统的崩溃,造成无法弥补的损失,系统的任何一个微小的修改都可能引入新的缺陷导致维护困难重重. 然而,如何从极端庞大复杂的系统中迅速及时地找到故障所在,却是行业的一大难点.目前国内软件测试基本处于两种状态:一是绝大多数企业采

PAT 甲级 A1042 (2019/01/24)

1 #include <cstdio> 2 const int N = 54; 3 char Color[5] = {'S', 'H', 'C', 'D', 'J'}; 4 int start[N+1], trans[N+1], end[N+1]; 5 int main() { 6 int n; 7 scanf("%d",&n); 8 for(int i = 1; i <= N; i++){ 9 start[i] = i; 10 } 11 for(int i

2019.8.24 TEST

T1 jigsaw 一开始看到这题的时候,这么多区间询问,修改,想到会用某种数据结构来维护,而且每次喊你异或上一次的答案,肯定是强制在线,这时就听到诸如树套树之类的神仙解法,但本sb蒟蒻并不会,就敲了个sb暴力线段树.原想到树套树肯定是本题正解,但实际上本题正解非常的不可思议. 先观察一下,答案都是在4-1000000之间的质数,所以肯定都是奇数,而每次都要异或答案,结果只能为1或2.所以我们可以反过来想,如果opt为奇数,那么肯定答案异或上奇数的最后一位是0,所以可以让操作符异或上2就是答案.

2019.9.24 网络ip小知识

原文链接:https://blog.csdn.net/faker_wang/article/details/80747407 :https://www.cnblogs.com/wktwj/p/10862618.html 摘抄一些我觉得比较需要知道的东西吧 子网掩码: 子网掩码(subnet mask)又叫网络掩码.地址掩码.子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码. 子网掩码不能单独存在,它必须结合IP地址一起使用.子网掩码只有一个作

2019.10.24 王俊懿_SPSS

数据文件的重置结构 横向结构(个案组) 纵向结构(变量组) 数据结构不符合分析方法的时候就需要重组 选定变量重组为个案 数据—重构 重构数据向导 选定变量重组为个案 将选定个案重构位变量 转置所有数据 变量组数目 一个 (如w1,w2,w3) 多个 (如p1,p2,p3,w1,w2,w3) 选择变量 个案组标识 使用个案号 使用选定变量 无 要转置的变量 目标变量 (名称) 周定交号 创建索引变量 一个 多个 无 创建一个索引变量 索引值具体有什么类型 连续效字 变量名 编辑索引变量名称和标签(

梦想MxWeb3D协同设计平台 2019.01.24更新

SDK开发包下载地址:http://www.mxdraw.com/ndetail_10124.html1.  编写快速入门教程2.  重构前端代码,支持一个页面多个三维控件同时加载,或二维和三维同时加载 3.  简化前端代码引用控件,只需一个函数就能动态创建三维控件4. 三维控件绘图区域,与界面UI分离5. 二维增加交互绘图接口6. 导出三维建模函数和三维运算函数提供了使用js开发的调用演示例程7. 增加导出二维图纸.遍历.对象查询.修改.绘图等函数 原文地址:https://www.cnblo