Codeforces Round #143 (Div. 2)

­­­­­好吧…Rating在上次#141之后1756.#143只有DIv2于是就打酱油来了.最后一题Tarjan_LCA忘光光了,比赛完才写的. 前四题比较简单 Rank80

 

A:

水.

#include<iostream>
#include<cstdio>

using namespace std;

int n,a,b,c;

int main()
{
    cin >> n;
    int cnt = 0;
    for (int i = 0;i<n;++i)
    {

        cin >> a >> b >> c;
        if (a+b+c>=2)
        {
            ++cnt;
        }
    }
    cout << cnt << endl;
    return 0;
}


 

B:

D = a1-a2+a3-a4....

然后Dp之.

#include<iostream>
#include<cstdio>

using namespace std;

bool vis[101][20010];
int from[101][20010];
int bj;
int n,d,l;

void dfs(int n,int cnt)
{
    if (n == 0) return ;
    if (n % 2 == 1)
    {
        dfs(n-1,cnt-from[n][cnt]);
    } else
    {
        dfs(n-1,cnt+from[n][cnt]);
    }
    cout << from[n][cnt] << " ";
}

void print()
{
    dfs(n,10000+d);
}

int main()
{
    cin >> n >> d >> l;
    vis[0][10000] = 1;
    for (int i = 1;i<=n;++i)
    for (int j = 0;j<=20000;++j)
    if (vis[i-1][j] == 1)
    {
        if (i % 2 == 1) bj = 1; else bj = -1;
        for (int k = 1;k<=l;++k)
        {
            vis[i][j+k*bj] = 1;
            from[i][j+k*bj] = k;
        }
    }
    if (vis[n][10000+d] == 0)
    {
        cout << "-1" << endl;
    }
     else print();
    return 0;
}

 

C:

最后答案最小数一定是数组里出现的数.

排序贪心之.

 

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

long long l,tot,ansA,ansB,tmp;
long long n,k;
long long a[200000];

int main()
{
    cin >> n >> k;
    for (long long i = 0;i<n;++i)
    {
        cin >> a[i];
    }
    sort(a,a+n);
    l = 0;
    tot = 0;
    ansA = 1; ansB = a[0];
    tmp = 1;
    for (long long i = 1;i<n;++i)
    {
        tot += (a[i]-a[i-1])*(i-l);
      //  cout << tot << endl;
        ++tmp;
        while (tot>k && l<=i)
        {
            tot -= a[i]-a[l];
            l++;
            --tmp;
        }
     // cout << tot << endl;
        if (tmp>ansA)
        {
            ansA = tmp;
            ansB = a[i];
        }
    }
    cout << ansA << " " << ansB << endl;
    return 0;
}

D:

读懂题目…然后就没有然后了..

 

#include<iostream>
#include<cstdio>

using namespace std;

int px,py,pz;
int x,y,z;
int a1,a2,a3,a4,a5,a6;
int ans;

int main()
{
    cin >> px >> py >> pz;
    cin >> x >> y >> z;
    cin >> a1 >> a2 >> a3 >> a4 >> a5 >> a6;
    ans = 0;
    if (py<0) ans += a1;
    if (py>y) ans += a2;
    if (pz<0) ans += a3;
    if (pz>z) ans += a4;
    if (px<0) ans += a5;
    if (px>x) ans += a6;
    cout << ans << endl;
    return 0;
}

 

E:

感觉这次就E题比较有点意思.

题目n(10^5)个点,m(10^5)条无向边,题目保证每个点最多只能出现在一个环里面.

10^5个询问(u,v)问其间的最短路径数.

 

因为保证了每个点只出现在一个环里面,所以可以求点双连通,然后缩成一个点.称这种店为环点这个时候整个图就变成树形了,没有反向边,交叉边.问题又变成求LCA了,(从数据规模就可以猜到一定会是这个样子的啦).求出简单路径上得环点个数Num,2^Num即为所求.因为进入环点就可以选择绕一圈,或者不饶^_^

 

#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>

using namespace std;

int n,m;

const int constN = 100100;

vector<int> adjacent[constN];
int color[constN];
int colorIndex = 0;
vector<int> colorToNode[constN];

void addEdge(int u,int v)
{
    adjacent[u].push_back(v);
    adjacent[v].push_back(u);
}

int DFN[constN];
int Low[constN];
stack<int> S;
bool inS[constN];
int index = 0;
bool visted[constN];
map<long long,int> mp;

void TarjanForGraph_Dfs(int u)
{
    int v = 0;
    visted[u] = 1;
    Low[u] = DFN[u] = ++index;
    S.push(u); inS[u] = 1;
    for (int j = 0;j<adjacent[u].size();++j)

    {
        v = adjacent[u][j];
        if (mp.count((long long)v*constN+u) > 0) continue;
        mp[(long long) u * constN + v] = 1;

        if (!visted[v])
        {
            TarjanForGraph_Dfs(v);
            Low[u] = min(Low[u],Low[v]);
        } else
        if (inS[v])
        {
            Low[u] = min(Low[u],DFN[v]);
        }
    }
    if (Low[u] == DFN[u])
    {
        ++colorIndex;
        do
        {
            v = S.top();
            color[v] = colorIndex;
            colorToNode[colorIndex].push_back(v);
            S.pop();
            inS[v] = 0;

        } while (u !=v);
    }
}

void TarjanForGraph()
{
    for (int i = 1;i<=n;++i)
    if (!visted[i]) TarjanForGraph_Dfs(i);
}

int DFNLca[constN];
int indexLca = 0;
int arr[constN*3];
int cnt = 0;
int Value[constN*3];
int totColor[constN];

void TarjanForLCA_Dfs(int u,int level,int colorNumber)
{
    if (colorToNode[u].size()>1) ++colorNumber;
    totColor[u] = colorNumber;

    visted[u] = 1;
    arr[++cnt] = u;
    Value[cnt] = level;
    DFNLca[u] = cnt;
    ++indexLca;
    int v;
    for (int i = 0;i<colorToNode[u].size();++i)
    {
        for (int j = 0;j<adjacent[ colorToNode[u][i] ].size();++j)
        {
            v = color[ adjacent[ colorToNode[u][i] ][j] ];
            if (!visted[v])
            {

                TarjanForLCA_Dfs(v,level+1,colorNumber);
                arr[++cnt] = u;
                Value[cnt] = level;
            }
        }
    }
}

int ST[constN*3][20];
int Minimum[constN*3][20];

void TarjanForLCA_ST()
{
    for (int i = 1;i<=cnt;++i)
    {
        ST[i][0] = Value[i];
        Minimum[i][0] = i;
    }
    for (int shift = 1;shift<20;++shift)
    {
        for (int i = 1;i<=cnt;++i)
        {
            if (i+(1<<shift)-1>cnt) break;
            ST[i][shift] = min(ST[i][shift-1],ST[i+ (1<<(shift-1)) ][shift-1] );
            if (ST[i][shift-1]<ST[i+ (1<<(shift-1)) ][shift-1] )
                Minimum[i][shift] = Minimum[i][shift-1];
            else
                Minimum[i][shift] = Minimum[i+ (1<<(shift-1)) ][shift-1];
        }
    }
}

void TarjanForLCA()
{
    for (int i = 0;i<constN;++i) visted[i] = 0;
    TarjanForLCA_Dfs(1,0,0);
    TarjanForLCA_ST();
}

int a,b;

const int MOD = 1000000007;

void print(int exp)
{
    long long ans = 1, mul = 2;
    while (exp) {
        if (exp & 1) ans = (long long)(ans) * mul % MOD;
        exp >>= 1;
        mul = (long long)(mul) * mul % MOD;
    }
    cout << ans << endl;
}

int main()
{
    cin >> n >> m;
    for (int i = 0;i<m;++i)
    {
        cin >> a >> b;
        addEdge(a,b);
        addEdge(b,a);
    }
    TarjanForGraph();
    TarjanForLCA();
    cin >> m;
    int shift = 0;
    int ans = 0;
    for (int i = 0;i<m;++i)
    {
        cin >> a >> b;
        a = DFNLca[color[a]];
        b = DFNLca[color[b]];
        if (a>b) swap(a,b);
        shift = (int) (log(b-a+1)/log(2));

        int Lca = Minimum[a][shift];
        if (ST[b-(1<<shift)+1][shift] < ST[a][shift])
            Lca = Minimum[b-(1<<shift)+1][shift];
        ans = totColor[arr[a]]+totColor[arr[b]]-2*totColor[arr[Lca]];
        if (colorToNode[arr[Lca]].size()>1) ++ans;
        print(ans);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值