Codeforces Round #948 (Div. 2) C

题目链接:http://codeforces.com/contest/948/problem/C

题意:小花很喜欢雪  就像每一个没有来过东北的孩子一样  给出n天的状态 包括每天收集到雪的体积与该天的温度 问每天会融化多少体积的雪  每一天收集到的雪自成一堆  温度为x则每一堆雪融化x体积  如果剩余不到x体积 就全部融化完

思路:这道题很容易想到是解法就是n^2的跑 这个题的n可以达到1e5 n^2的跑会超时  想到一个优化就是开两个queue 不停地把还剩下雪的体积存起来  省去了检索体积为零的时间  但是在第11组的时候还是超时 

题解:输入过程不用说了  我的想法是对每天的温度遍历一遍  正解是对每天的雪量遍历一遍  每天的雪使用二分查找找到这个雪在那一天会被用完 二分查找比扫一遍省很多时间  然后把这个范围内每天的ans加上对应的温度 最后一天加温度还是剩余的雪量需要特殊考虑 这样的话需要预处理出来温度的前缀和  用在二分查找里面 基本上是nlog的复杂度 但是感觉比上面那个想法省不了多少时间啊 上面那个也是每天的ans直接更新 更新的次数也是有多少雪对这一天有贡献就加上 不知道什么区别 先试试

原始想法 第十一组超时

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>

using namespace std;

long long n;
long long v[100010];
long long t;
long long ans;
long long num;
long long f;

void read(long long &x){
    x=0;char c=getchar();
    while(c<'0' || c>'9')c=getchar();
    while(c>='0' && c<='9'){
        x=x*10+c-'0';
        c=getchar();
    }
}

void write(long long x){
    if(x==0){putchar(48);return;}
    int len=0,dg[20];
    while(x>0){dg[++len]=x%10;x/=10;}
    for(int i=len;i>=1;i--)putchar(dg[i]+48);
}

int main()
{
    while( scanf("%I64d" , &n) != EOF )
    {
        queue<int>Q[2];
        for(long long i=0; i<n; i++)
        {
            read(v[i]);
        }
        for(long long i=0; i<n; i++)
        {
            read(t);
            ans = 0;
            num = i%2;
            Q[num].push(v[i]);
            while( !Q[num].empty() )
            {
                f = Q[num].front();
                Q[num].pop();
                if( f >= t)
                {
                    ans += t;
                    Q[!num].push(f-t);
                }
                else
                {
                    ans += f;
                }
            }
            if(i != 0)
                printf(" %I64d" , ans);
            else
                printf("%I64d" , ans);
        }
        printf("\n");

    }


    return 0;
}
第十一组超时

写法不对 第四组就超时

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>

using namespace std;

int n , v[100010] , t[100010];
int sum[100010];
int ans[100010];

int fin(int x)
{
    int l , r , mid , res;
    l = x;
    r = n;
    res = n+1;
    while( l<= r)
    {
        mid = (l+r)/2;
//        printf("%d......%d.....%d\n" , l , r , mid);
        if((sum[mid]-sum[x]+t[x]) >= v[x])
        {
            res = mid;
            r = mid-1;
        }
        else
        {
            l = mid+1;
        }
    }
    return res;
}

int main()
{
    sum[0] = 0;
    while( scanf("%d" , &n) != EOF )
    {
        memset(ans , 0 , sizeof(ans));
        for(int i=1; i<=n; i++)
        {
            scanf("%d" , &v[i]);
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d" , &t[i]);
            sum[i] = sum[i-1]+t[i];
        }
        for(int i=1; i<=n; i++)
        {
            int r = fin(i);
//            printf(".......%d\n" , r);
            if(sum[r]-sum[i]+t[i]==v[i])
            {
                for(int j=i; j<=r; j++)
                    ans[j] += t[j];
            }
            else
            {
                for(int j=i; j<r; j++)
                    ans[j] += t[j];
                ans[r] += v[i]-(sum[r-1]-sum[i]+t[i]);
            }
            if(i!=1)
            printf(" %d" , ans[i]);
            else if(i==1)
                printf("%d" , ans[i]);
        }

    }

    return 0;
}
第四组超时

将数组修改为两个数组f[]数组记录会融化多少个完整的t体积  w记录会融化多少个剩余的体积 最后用f[]*t[]+w[]  会到十一组超时

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>

using namespace std;

long long n , v[100010] , t[100010];
long long sum[100010];
long long f[100010];
        long long w[100010];

long long fin(long long x)
{
    long long l , r , mid , res;
    l = x;
    r = n;
    res = n+1;
    while( l<= r)
    {
        mid = (l+r)/2;
//        printf("%I64d......%I64d.....%I64d\n" , l , r , mid);
        if((sum[mid]-sum[x]+t[x]) >= v[x])
        {
            res = mid;
            r = mid-1;
        }
        else
        {
            l = mid+1;
        }
    }
    return res;
}

int main()
{
    sum[0] = 0;
    while( scanf("%I64d" , &n) != EOF )
    {
        memset(f , 0 , sizeof(f));
        memset(w , 0 , sizeof(w));
        for(long long i=1; i<=n; i++)
        {
            scanf("%I64d" , &v[i]);
        }
        for(long long i=1; i<=n; i++)
        {
            scanf("%I64d" , &t[i]);
            sum[i] = sum[i-1]+t[i];
        }
        for(long long i=1; i<=n; i++)
        {
            long long r = fin(i);
//            printf(".......%I64d\n" , r);
                for(long long j=i; j<r; j++)
                    f[j]++;
                w[r] += v[i]-(sum[r-1]-sum[i]+t[i]);
            if(i!=1)
                printf(" %I64d" , f[i]*t[i]+w[i]);
            else if(i==1)
                printf("%I64d" , f[i]*t[i]+w[i]);
        }

    }

    return 0;
}
第十一组超时

 把f[]不设置成全部更新 只设置成更新断电 逐渐累加过去 这个是个小技巧 要记住  还有就是特殊样例

4

0 0 0 0

1 2 3 4

需要试一下

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>

using namespace std;

long long n;
long long v[100010] , t[100010];
long long sum[100010];
long long f[100010] , w[100010];

long long fin(long long x)
{
    v[x] += sum[x-1];
    long long l = 1;
    long long r = n;
    long long mid;
    long long res;
    res = n+1;
    while( l <= r)
    {
        mid = (l+r)/2;
        if(sum[mid] >= v[x])
        {
            res = mid;
            r = mid-1;
        }
        else
        {
            l = mid+1;
        }
    }
    return res;

}

int main()
{
    sum[0] = 0;
    while( scanf("%I64d" , &n) != EOF )
    {
        memset(f , 0 , sizeof(f));
        memset(w , 0 , sizeof(w));
        for(long long i=1; i<=n; i++)
        {
            scanf("%I64d" , &v[i]);
        }
        for(long long i=1; i<=n; i++)
        {
            scanf("%I64d" , &t[i]);
            sum[i] = sum[i-1]+t[i];
        }
        long long zz;
        zz = 0;
        for(long long i=1; i<=n; i++)
        {
            long long r = fin(i);
//            printf("%I64d.........\n" , r);
            if(r>i && r != i)
            {
                f[i]++;
                f[r]--;
                w[r] += v[i]-sum[r-1];
            }
            else
            {
                w[i] += v[i]-sum[i-1];
            }
            zz += f[i];
            if(i!=1)
                putchar(' ');
            printf("%I64d" , zz*t[i]+w[i]);
        }
        printf("\n");
    }


    return 0;
}

  

posted @ 2018-03-18 12:26  Flower_Z  阅读(243)  评论(0编辑  收藏  举报