Codeforces 816B & 816C & 816D Karen and ......(不正经专场)

主要不是为了写816B和816C的,主要是为了做个记录。
http://codeforces.com/problemset/problem/816/B
http://codeforces.com/problemset/problem/816/C
一次提交,6.25日模拟。
http://codeforces.com/problemset/problem/816/D
十二次提交,7.1日搞定(不容易啊)。

//B题代码
int ans[200050], st[200050], en[200050], c[200050];
int n,k,m;
pair <int, int> p[200050];
int main()
{
    cin >> n >> k >> m;
    for(int i=0;i<n;i++)
    {
        int a,b;
        cin>>a>>b;
        b++;
        st[a]++;
        en[b]++;
    }
    int cur = 0;
    for(int i = 1; i <= 200000; i++)
    {
        cur += st[i] - en[i];
        if(cur >= k)
            c[i] = 1;
    }
    for(int i = 1; i <= 200001; i++)
        ans[i] = ans[i - 1] + c[i - 1];
    for(int i=0;i<m;i++)
    {
        int a,b;
        cin>>a>>b;
        b++;
        cout << ans[b] - ans[a] << endl;
    }
    return 0;
}
//C题代码
using namespace std;
const int maxn=105;
int n,m,a[maxn][maxn],b[maxn][maxn];
int r[maxn],c[maxn];
int ans=-1,mi;
bool jud1(int t)
{
    for (int j=1;j<=m;j++)
    {
        b[1][j]-=t;
        if(b[1][j]<0)
        {
            return true;
        }
    }
    return false;
}
int jud2(int t)
{
    for (int i=2;i<=n;i++)
    {
        int p=b[i][1]-b[1][1];
        if (p<0)
            return -1;
        t+=p;
        bool f=false;
        for (int j=1;j<=m;j++)
        {
            b[i][j]-=p;
            if(b[i][j]<0)
            {
                f=true;
                break;
            }
        }
        if (f)
            return -1;
    }
    return t;
}
int jud3(int t)
{
    for (int j=1;j<=m;j++)
    {
        for (int i=2;i<=n;i++)
            if (b[i][j]!=b[i-1][j])
                return -1;
        t+=b[1][j];
    }
    return t;
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            cin>>a[i][j];
    for (int t=0;t<=500;t++)
    {
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                b[i][j]=a[i][j];
        if(jud1(t))
            continue;
        int t1=jud2(t);
        if(t1==-1)
            continue;
        t1=jud3(t1);
        if(t1==-1)
            continue;
        if (ans==-1 || ans>t1)
        {
            ans=t1;
            mi=t;
        }
    }
    cout<<ans<<endl;
    if(ans==-1)
        return 0;
    int t=mi,x=mi;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            b[i][j]=a[i][j];
    for (int j=1;j<=m;j++)
        b[1][j]-=t;
    r[1]=t;
    for (int i=2;i<=n;i++)
    {
        int p=b[i][1]-b[1][1];
        r[i]=p;x+=p;
        for (int j=1;j<=m;j++)
            b[i][j]-=p;
    }
    for (int j=1;j<=m;j++)
        c[j]=b[1][j];
    for (int i=1;i<=n;i++)
        for (int j=1;j<=r[i];j++)
            cout<<"row "<<i<<endl;
    for (int i=1;i<=m;i++)
        for (int j=1;j<=c[i];j++)
            cout<<"col "<<i<<endl;
    return 0;
}

下面就是D啦,题目意思是这样滴,Karen去考试,题目是n个数字,用杨辉三角的方法用加和减运算着n个数,第一个符号为加号,然后跟着减号,然后第二行,以此类推,直到算出最终的一个数。
一开始TLE的方法是这样滴(虽然估计的时间复杂度并没有超时,匪夷又所思),如果n是偶数,先化为奇数,其实这一步可以省去,但假如写个函数的话到后面也挺实用的,化为奇数后特判在不在4以内,如果在直接输出结果,不在就继续往下做。
原本如果暴力的话时间复杂度是O(N^2)的,因为每一层只能消去一个数,无疑是非常慢的,所以我优化了一下,每一层消去四个数,也就是合并5个数,这样速度就提高很多。
这样的确是可以,但可能是因为vector的常数问题,仍然TLE,所以要在一些细节上下功夫(由于不想慢慢改,就重写了一遍)
1.加号减号的转换问题,原本是用两个if来判断正负,实则不用,只要用一个变量每次乘以-1就行了。
2.谁说要用vector了,其实两个数组就足够,而且我们可以折半!原本的n我们不把它化成奇数,把它化成偶数,这样,两边的符号完全相同,只要判断最后的符号即可,然后把两边的x,y运算就好了,所以程序能够更快。
这道题最主要的还是计算,手推公式,加油!

原文地址:https://www.cnblogs.com/NightRaven/p/9333253.html