《牛客练习赛67》

A:因为数太大,所以按字符串存即可

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<LL,int> pii;
const int N = 1e5+5;
const int M = 2e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read()
{
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    string s;
    while(getline(cin,s))
    {
        string t = "";
        vector<string> ans;
        int pre = 0;
        for(int i = 0;i < s.size();++i)
        {
            if(s[i] >= '0' && s[i] <= '9')
            {
                if(s[i] == '0' && t == "") pre++;
                else t += s[i];
            }
            else
            {
                if(t != "") ans.push_back(t);
                else if(t == "" && pre != 0) ans.push_back("0");
                pre = 0;
                t = "";
            }
        }
        if(t != "") ans.push_back(t);
        else if(t == "" && pre != 0) ans.push_back("0");
        if(ans.size() == 0) cout << endl;
        else
        {
            for(int i = 0;i < ans.size();++i) 
            {
                cout << ans[i];
                if(i == ans.size()-1) cout << endl;
                else cout << " ";
            }
        }
    }
   // system("pause");
    return 0;
}
View Code

B:显然是最大的那个数

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<LL,int> pii;
const int N = 1e5+5;
const int M = 2e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read()
{
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
int main()
{
    int ca;ca = read();
    while(ca--)
    {
        int n;n = read();
        int mx = -1;
        for(int i = 1;i <= n;++i)
        {
            int x;x = read();
            mx = max(mx,x);
        }
        if(mx < 0) mx = 0;
        printf("%d\n",mx);
    }
   // system("pause");
    return 0;
}
View Code

C:手推几个就可以发现3的倍数必败,其他必胜

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<LL,int> pii;
const int N = 1e5+5;
const int M = 2e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline LL read()
{
    LL x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
int main()
{
    int ca;ca = read();
    while(ca--)
    {
        LL n;n = read();   
        if(n%3 == 0) printf("Frame\n");
        else printf("Alan\n");
    }
  //  system("pause");
    return 0;
}
View Code

D:DP转移

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<LL,int> pii;
const int N = 1e5+5;
const int M = 2e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline LL read()
{
    LL x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
int a[N];
int dp[N][2],f[N];//dp[i][0]-全变0的最小代价,dp[i][1]-全变1的最小代价
int main()
{
    int n;n = read();
    for(int i = 1;i <= n;++i) a[i] = read();
    int sum = 0;
    if(a[1] == 1)
    {
        dp[1][1] = 0;
        dp[1][0] = 1;
    }
    else
    {
        dp[1][0] = 0;
        dp[1][1] = 1;
    }
    for(int i = 2;i <= n;++i)
    {
        if(a[i] == 0)
        {
            dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1);
            dp[i][1] = min(dp[i-1][1]+1,dp[i-1][0]+1);
        }
        else
        {
            dp[i][1] = min(dp[i-1][1],dp[i-1][0]+1);
            dp[i][0] = min(dp[i-1][1]+1,dp[i-1][0]+1);
        }
       // printf("i is %d dp0 is %d dp1 is %d\n",i,dp[i][0],dp[i][1]);
    }
    int ans = min(dp[n][0],dp[n][1]+1);
    printf("%d\n",ans);
    //system("pause");
    return 0;
}
View Code

E:

注意lowbit的定义是最小的为1的二进制位。

首先暴力建边n*2,可以不行。

这里建32个虚拟点,表示二进制位i的站点。

那么可以发现,如果这个数i位上是1,那么就可以和代表i的虚拟点连边,代价为(1<<i)。

然后虚拟点到其他点的代价都为0.最后跑一次最短路即可。

那么,为什么这样建边就能保证最小了,不会比原先的答案还小吗?

可以发现,如果可以建边,那么说明这个数这个位上有1,如果更低位上有1,那么会满足lowbit的定义。

显然,会用更低的代价去松弛答案,这样可以保证到最小。至于不会超答案,这很显然,如果能到,说明可以松弛到。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<LL,int> pii;
const int N = 1e5+5;
const int M = 2e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline LL read()
{
    LL x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
LL a[N],dis[N<<1];
struct Node{int to;LL dis;};
vector<Node> G[N<<1];
/*
[0,34] - []
*/
int n,m;
void slove()
{
    for(int i = 1;i <= m;++i) dis[i] = INF;
    priority_queue<pii,vector<pii>,greater<pii> > Q;
    dis[1] = 0;
    Q.push(pii{0,1});
    while(!Q.empty())
    {
        int u = Q.top().second;
        LL d = Q.top().first;
        Q.pop();
        if(d > dis[u]) continue;
        for(auto t : G[u])
        {
            if(dis[t.to] > dis[u]+t.dis)
            {
                dis[t.to] = dis[u]+t.dis;
                Q.push(pii{dis[t.to],t.to});
            }
        }
    }
}   
int main()
{
    int ca;ca = read();
    while(ca--)
    {
        n = read();
        for(rg int i = 1;i <= n;++i) a[i] = read();
        m = n+35;
        for(rg int i = 1;i <= m;++i) G[i].clear();
        for(rg int i = 1;i <= n;++i)
        {
            for(rg int j = 0;j < 35;++j)
            {
                if((a[i]>>j)&1) 
                {
                    G[i].push_back(Node{n+j+1,1LL<<j});
                    G[n+j+1].push_back(Node{i,0});
                }
            }
        }
        slove();
        if(dis[n] == INF) printf("Impossible\n");
        else printf("%lld\n",dis[n]); 
    }
    //system("pause");    
    return 0;
}
View Code

F:

一开始一直在想树剖来着。。(不过树剖也可以做)。

解法:可以发现,对于区间[L,R]里的最大权值,显然是区间的直径(即区间内最远的两个点)

那么我们可以用st[i][j]来表示i位置包含i后面开始2^j个位置里的直接的两个数,因为是两个数,可以要用pair来存。

那么st[i][j]合并,这里可以发现,是类似st表的合并。从st[i][j-1]和st[i+(1<<j)][j-1]来转移。

这里我们还可以发现的是,对于两个区间的直径的合并,显然新的直径是四个点里(即原先两个区间的直径点)距离最远的两个点。(这也很显然,可以画图理解,就三种链与点的关系)

那么我们就可以转移最大值。到这里就差不多了。

但是这题卡时间卡的厉害。vector被卡。然后因为LCA也用了太多次了,必须用ST来求LCA,不然也会T

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 3e5+5;
const int M = 2e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read()
{
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
int lg[N<<1],head[N],f[N<<1][20],dfn[N],dep[N];
LL way[N];
int n,q,cnt = 0,tot = 0;
pii st[N][32];
struct Node{int to,next;LL dis;}e[N<<1];
inline void add(int u,int v,LL w)
{
    e[++cnt].to = v,e[cnt].dis = w,e[cnt].next = head[u],head[u] = cnt;
}
void dfs(int u,int fa)
{
    dep[u] = dep[fa]+1;
    f[++tot][0] = u;
    dfn[u] = tot;
    for(rg int i = head[u];i;i = e[i].next)
    {
        if(e[i].to == fa) continue;
        way[e[i].to] = way[u]+e[i].dis;
        dfs(e[i].to,u);
        f[++tot][0] = u;
    }
}
void init()
{
    lg[1] = 0;for(rg int i = 2;i <= tot;++i) lg[i] = lg[i>>1]+1;
    for(rg int j = 1;j <= 19;++j)
    {
        for(rg int i = 1;i+(1<<j)-1 <= tot;++i)
        {
            if(dep[f[i][j-1]] <= dep[f[i+(1<<j-1)][j-1]]) f[i][j] = f[i][j-1];
            else f[i][j] = f[i+(1<<j-1)][j-1];
        }
    }
}
int LCA(int x,int y)
{
    x = dfn[x],y = dfn[y];
    if(x > y) swap(x,y);
    int k = lg[y-x+1];
    if(dep[f[x][k]] < dep[f[y-(1<<k)+1][k]]) return f[x][k];
    return f[y-(1<<k)+1][k];
}
LL dis(int x,int y)
{
    return way[x]+way[y]-2LL*way[LCA(x,y)];
}
pii check(pii a,pii b)
{
    LL ma1 = dis(a.first,b.first);
    LL ma2 = dis(a.first,b.second);
    LL ma3 = dis(a.second,b.first);
    LL ma4 = dis(a.second,b.second);
    LL ma5 = dis(a.first,a.second);
    LL ma6 = dis(b.first,b.second);
    if(ma1 >= ma2 && ma1 >= ma3 && ma1 >= ma4 && ma1 >= ma5 && ma1 >= ma6) return pii{a.first,b.first};
    if(ma2 >= ma1 && ma2 >= ma3 && ma2 >= ma4 && ma2 >= ma5 && ma2 >= ma6) return pii{a.first,b.second};
    if(ma3 >= ma1 && ma3 >= ma2 && ma3 >= ma4 && ma3 >= ma5 && ma3 >= ma6) return pii{a.second,b.first};
    if(ma4 >= ma1 && ma4 >= ma2 && ma4 >= ma3 && ma4 >= ma5 && ma4 >= ma6) return pii{a.second,b.second};
    if(ma5 >= ma1 && ma5 >= ma2 && ma5 >= ma3 && ma5 >= ma4 && ma5 >= ma6) return pii{a.first,a.second};
    return pii{b.first,b.second};
}
void pre()
{
    for(rg int i = 1;i <= n;++i) st[i][0] = pii{i,i};
    for(rg int j = 1;j <= 19;++j)
    {
        for(rg int i = 1;i+(1<<j)-1 <= n;++i)
        {
            st[i][j] = check(st[i][j-1],st[i+(1<<(j-1))][j-1]);
        }
    }
}
LL query(int x,int y)
{
    int k = lg[y-x+1];
    pii ma = check(st[x][k],st[y-(1<<k)+1][k]);
    return dis(ma.first,ma.second);
}
int main()
{
    n = read(),q = read();
    for(rg int i = 1;i < n;++i)
    {
        int u,v,w;u = read(),v = read(),w = read();
        add(u,v,w);add(v,u,w);
    }
    dfs(1,0);
    init();
    pre();
    while(q--)
    {
        int L,r;L = read(),r = read();
        printf("%lld\n",query(L,r));
    }
    system("pause");    
    return 0;
}
View Code

 

posted @ 2020-08-15 15:28  levill  阅读(164)  评论(0编辑  收藏  举报