zoukankan      html  css  js  c++  java
  • 数据结构1

    集合合并

    有n个元素,每个元素在不同的集合内,给出n-1个操作合并两个元素所在集合,保证之前不在同一集合。

    有m个询问,(x,y)是在第几次操作后第一次位于同一集合。

    n<=1e5

    题解

    操作完之后就是一棵树,任意两点间只有一条简单路径,只要路径上的边都建好就联通,所以就是查路径最大值,边权为是第几次操作。

    那么用倍增维护就好了,注意细节。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxn=200005;
    int n,m;
    int dep[maxn],fa[maxn][25],mx[maxn][25];//mx:从i到走2^j步到达的点的路径最大值 
    int cnt,head[maxn];
    struct edge{
        int x,y,val,next;
    }e[maxn<<1];
    
    template<class T>inline void read(T &x){
        x=0;int f=0;char ch=getchar();
        while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x= f ? -x : x ;
    }
    
    void add(int x,int y,int val){
        e[++cnt]=(edge){x,y,val,head[x]};
        head[x]=cnt;
    }
    
    void dfs(int x){
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(y==fa[x][0]) continue;
            dep[y]=dep[x]+1;
            fa[y][0]=x;
            mx[y][0]=e[i].val;
            dfs(y);
        }
    }
    
    void rmq(){
        for(int j=1;j<=20;j++)
         for(int i=1;i<=n;i++){
              fa[i][j]=fa[fa[i][j-1]][j-1];
              mx[i][j]=max(mx[i][j-1],mx[fa[i][j-1]][j-1]);
         }
    }
    
    int query(int x,int y){
        if(dep[x]<dep[y]) swap(x,y);
        int delt=dep[x]-dep[y];
        int ret=0;
        for(int i=0;delt;i++,delt>>=1)
         if(delt&1){
              ret=max(ret,mx[x][i]);
              x=fa[x][i];
         }
        if(x==y) return ret;
        for(int i=20;fa[x][0]!=fa[y][0];i--)
         if(fa[x][i]!=fa[y][i]){
              ret=max(ret,mx[x][i]);
              ret=max(ret,mx[y][i]);
              x=fa[x][i];
              y=fa[y][i];
         }
        return max(ret,max(mx[x][0],mx[y][0]));
    }
    
    int main(){
        freopen("union.in","r",stdin);
        freopen("union.out","w",stdout);
        read(n);read(m);
        for(int i=1;i<n;i++){
            int x,y;read(x);read(y);
            add(x,y,i);
            add(y,x,i);
        }
        dfs(1);
        rmq();
        for(int i=1;i<=m;i++){
            int x,y;
            read(x);read(y);
            printf("%d
    ",query(x,y));
        }
    }
    union

    最长公共子序列

    给出两个长度为n的排列,求最长公共子序列。

    题解

    模板题,将a数组映射到b数组,那么b数组就变成了每个数在a数组中的下标。

    然后求lis即可。

    维护f数组:长度为i的上升子序列末尾最小是f[i],这个数组是单增的(假设f[i]>f[j]&&i<j,但是长度为j的上升子序列中,选取前i个数,第i个数<f[j]<f[i],不满足定义)

    按顺序搞b数组,对于b[i]找f数组中最大的j使得b[i]>f[j],然后组成一个长度为j+1的上升子序列,f[j+1]=b[i](不存在原来的f[j+1]<b[i],不然找到的就是j+1),二分查找

    最后看f数组中最大的不为最大值的位置。

    注意a和b,还有在二分里面传入的是b[i]的话,就不要写b[x](我写成了a[x]可还行)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxn=100005;
    int n;
    int a[maxn],mp[maxn],b[maxn],f[maxn];
    
    template<class T>inline void read(T &x){
        x=0;int f=0;char ch=getchar();
        while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x= f ? -x : x ;
    }
    
    int find(int x){
        int l=0,r=n,ans=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(x>f[mid]) ans=mid,l=mid+1;
            else r=mid-1;
        }
        return ans;
    }
    
    int main(){
        freopen("lcs.in","r",stdin);
        freopen("lcs.out","w",stdout);
        read(n);
        for(int i=1;i<=n;i++){
            read(a[i]);
            mp[a[i]]=i;
        }
        for(int i=1;i<=n;i++){
            read(b[i]);
            b[i]=mp[b[i]];
        }
        for(int i=1;i<=n;i++) f[i]=0x3f3f3f;
        for(int i=1;i<=n;i++){
            int x=find(b[i]);
            f[x+1]=b[i];
        }
        for(int i=n;i;i--)
         if(f[i]!=0x3f3f3f){
              printf("%d",i);
              return 0;
         }
    }
    lcs

    文件系统

    就是模拟创建文件和文件夹,删除文件和文件夹,返回上一级,输出这一级的文件和文件夹。

    用map模拟即可,一开始写的map<string,int>,结果错了,就改成了hash,结果是建文件夹写成了==。

    然后文件也是这么写的(没发现)

    #include<bits/stdc++.h>
    using namespace std;
    #define ull unsigned long long
    const int maxn=505;
    const ull base=10007;
    int q,cnt,now;
    char c[15];
    string ch;
    struct node{
        int id,belong;
        bool operator < (const node a) const {return a.id<id;}
    };
    struct point{
        int fa;
        map<ull,int> son[2];//0:文件 1:文件夹 
        map<int,string> mp[2];
        vector<node> s[2];
    }tr[maxn];
    
    ull get(){
        ull ret=0;
        int len=ch.size();
        for(int i=0;i<len;i++) ret=ret*base+ch[i];
        return ret;
    }
    
    void print(){
        priority_queue<node> q,no;
        for(unsigned int i=0;i<tr[now].s[0].size();i++) q.push(tr[now].s[0][i]);
        for(unsigned int i=0;i<tr[now].s[1].size();i++) no.push(tr[now].s[1][i]);
        while(!q.empty()){
            while(!no.empty()&&q.top().id==no.top().id) {q.pop();no.pop();}
            node x=q.top();
            q.pop();
            cout<<tr[now].mp[x.belong][x.id]<<" ";
            if(x.belong) cout<<"<D>";
            else cout<<"<F>";
            putchar(10);
        }
    }
    
    int main(){
        freopen("files.in","r",stdin);
        freopen("files.out","w",stdout);
        now=++cnt;
        scanf("%d",&q);
        while(q--){
            scanf("%s",c);
            if(c[0]=='l') {print();continue;}
            cin>>ch;
            ull val=get();
            if(c[0]=='c'){
                if(ch[0]=='.'){//退出 
                    if(!tr[now].fa) printf("No parent directory!
    ");
                    else now=tr[now].fa;
                }
                else {//进入 
                    if(tr[now].son[1][val]) now=tr[now].son[1][val];
                    else printf("No such directory!
    ");
                }
            }
            else if(c[0]=='t'){//创建文件 
                if(tr[now].son[0][val]) printf("File already exists!
    ");
                else {
                    tr[now].son[0][val]=++cnt;
                    tr[now].mp[0][cnt]=ch;
                    tr[now].s[0].push_back((node){cnt,0});
                }
            }
            else if(c[0]=='r'){
                if(strlen(c)==2) {//删除文件 
                    if(!tr[now].son[0][val]) printf("No such file!
    ");
                    else {
                        int x=tr[now].son[0][val];
                        tr[now].son[0][val]=0;
                        tr[now].s[1].push_back((node){x,0});
                    }
                }
                else {//删除文件夹 
                    if(!tr[now].son[1][val]) printf("No such directory!
    ");
                    else {
                        int x=tr[now].son[1][val];
                        tr[now].son[1][val]=0;
                        tr[now].s[1].push_back((node){x,1});
                    }
                }
            }
            else if(c[0]=='m'){//创建文件夹 
                if(tr[now].son[1][val]) printf("Directory already exists!
    ");
                else {
                    tr[now].son[1][val]=++cnt;
                    tr[cnt].fa=now;
                    tr[now].mp[1][cnt]=ch;
                    tr[now].s[0].push_back((node){cnt,1});
                }
            }
        }
    }
    /*
    3
    mkdir standy
    touch totalfrank
    ls
    */
    files
  • 相关阅读:
    JMS ActiveMQ研究文档
    HDD-FAT32 ZIP-FAT32
    C++中出现的计算机术语2
    提供一个免费的CSDN下载账号
    读完了csapp(中文名:深入理解计算机系统)
    IOS成长之路-Nsstring中搜索方法rangeOfString
    PHP汉字转拼音的两种方法+PHP提取汉字(中文)方法
    最小二乘法
    防止tab页重复的去请求服务端
    探索Android中的Parcel机制(上)
  • 原文地址:https://www.cnblogs.com/sto324/p/11580004.html
Copyright © 2011-2022 走看看