zoukankan      html  css  js  c++  java
  • 2018CCPC女生赛(树上莫队)

    签到题这里久懒得写了。

    B - 缺失的数据范围

    Total Submission(s): 2602    Accepted Submission(s): 559

    题意:求最大的N,满足N^a*[log2(N)]^b<=K;

    思路:二分即可,log2要手写,然后就是注意判pow是否超过long long。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1000100;
    const ll inf=1e18;
    ll A,B,K,ans,aa[61];
    ll Log(ll x){
        int pos=lower_bound(aa+1,aa+60+1,x)-aa;
        return pos;
    }
    bool check(ll x){
        ll a=1,res=1;
        ll b=Log(x);// cout<<b<<" "<<aa[b]<<" ";
        for(int i=1;i<=A;i++){
            if(a>K/x) return false;
            a=a*x; if(a>K) return false;
        }
        for(int i=1;i<=B;i++){
            if(res>K/b) return false;
            res=res*b; if(res>K) return false;
        }
        //cout<<a<<" "<<b<<endl;
        if(a>K/res) return false;
        if(a*res<=K) return true;
    }
    int main()
    {
        int T;
        aa[0]=1;
        for(int i=1;i<=60;i++) aa[i]=aa[i-1]*2;
        scanf("%d",&T);
        while(T--){
            scanf("%lld%lld%lld",&A,&B,&K); ans=0;
            ll L=1,R=K;
            while(L<=R){
                ll Mid=(L+R)/2;
                if(check(Mid)) ans=Mid,L=Mid+1;
                else R=Mid-1;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    E - 对称数

    Total Submission(s): 469    Accepted Submission(s): 88

    题意:给出一棵带点权的树,Q次询问,每次询问给出(u,v),求这个路径上最小的出现次数位偶数的正整数。

    思路:树上莫队:皇室联邦法分块,括号法移动区间。

    皇室联邦法分块:即按照DFS虚分块。

    括号法:dfs时,记录第一次访问时间戳in[]和最后一次访问时间戳out[]。如果访问路径(u,v),保证in[u]<in[v]起对应的区间就是:

    1,LCA==u,对应[in[u],in[v]];

    2,LCA!=u,对应[out[u],in[v]]+LCA;LCA单独考虑为pre,不要忽略。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=400010;
    int a[maxn],Laxt[maxn],Next[maxn],To[maxn],cnt,B;
    int g[maxn],dep[maxn],fa[maxn][20],ans[maxn],scc,tot;
    int in[maxn],out[maxn],p[maxn];
    bitset<maxn>Set;
    struct in{
        int u,v,id;
        friend bool operator <(in ww,in vv){
            if(g[ww.u]==g[vv.u]) return g[ww.v]<g[vv.v];
            return g[ww.u]<g[vv.u];
        }
    }s[maxn];
    void add(int u,int v)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
    }
    void dfs(int u,int f)
    {
        fa[u][0]=f;  dep[u]=dep[f]+1;
        if(tot%B==0) scc++;  g[u]=scc;
        in[u]=++tot;  p[tot]=a[u];
        for(int i=Laxt[u];i;i=Next[i]){
            if(To[i]!=f) dfs(To[i],u);
        }
        out[u]=++tot; p[tot]=a[u];
    }
    int LCA(int u,int v)
    {
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=18;i>=0;i--)
             if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
        if(u==v) return u;
        for(int i=18;i>=0;i--)
            if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
        return fa[u][0];
    }
    int main()
    {
        int T,N,M,u,v,Lca;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&N,&M); B=sqrt(N);
            cnt=0; rep(i,1,N) Laxt[i]=0;
            rep(i,1,N) scanf("%d",&a[i]);
            rep(i,1,N-1){
                scanf("%d%d",&u,&v);
                add(u,v); add(v,u);
            }
            tot=0; scc=0; dfs(1,0);
            rep(i,1,18) rep(j,1,N) fa[j][i]=fa[fa[j][i-1]][i-1];
            rep(i,1,M) scanf("%d%d",&s[i].u,&s[i].v),s[i].id=i;
            rep(i,1,M) if(in[s[i].u]>in[s[i].v]) swap(s[i].u,s[i].v);
            sort(s+1,s+M+1);
            Set.set();
            int L=1,R=1,pre=0; Set.flip(p[1]);
            rep(i,1,M) {
                Set.flip(pre);
                int Lca=LCA(s[i].u,s[i].v),l,r;
                if(Lca==s[i].u) l=in[s[i].u],r=in[s[i].v],pre=0;
                else l=out[s[i].u],r=in[s[i].v],Set.flip(a[Lca]),pre=a[Lca];
                while(l<L) Set.flip(p[--L]);
                while(l>L) Set.flip(p[L++]);
                while(r>R) Set.flip(p[++R]);
                while(r<R) Set.flip(p[R--]);
                int pos=Set._Find_next(0);
                ans[s[i].id]=pos;
            }
            rep(i,1,M) printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code

    I - 回文树

    题意:给出一棵带权树,点权随机给出,求树上有多少回文串。

    思路:由于是随机,我们大胆猜测,只存在长度为1,2和3的回文串。

    Total Submission(s): 198    Accepted Submission(s): 45

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    int a[maxn]; map<int,int>mp[maxn];
    int main()
    {
        int N,T,u,v;
        scanf("%d",&T);
        while(T--){
            int ans=0;
            scanf("%d",&N);
            rep(i,1,N) mp[i].clear();
            rep(i,1,N) scanf("%d",&a[i]);
            rep(i,1,N-1){
                scanf("%d%d",&u,&v);
                if(a[u]==a[v]) ans++;
                ans+=mp[u][a[v]];
                ans+=mp[v][a[u]];
                mp[u][a[v]]++; mp[v][a[u]]++;
            }
            printf("%d
    ",ans+N);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    面试题
    网络编程-1
    excel文件导入数据库--jxl包
    excel文件导入数据库
    1113 Integer Set Partition (25 分)集合分割
    1120 Friend Numbers (20 分)set的使用
    1099 Build A Binary Search Tree (30 分)
    1092 To Buy or Not to Buy (字符串删除)
    1127 ZigZagging on a Tree (30 分)树的层次遍历
    1155 Heap Paths (30 分)判断是否是一个堆
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10095643.html
Copyright © 2011-2022 走看看