zoukankan      html  css  js  c++  java
  • codeforces975C 题解

    题意

    有从前到后排列的n个勇士,第i回合射出ki发箭,一共射q回合,每一次射箭会射到当前在头上还未倒下的勇士,勇士i被射中ai次之后会倒下,所有勇士都倒下之后会在本回合内复活。

    笺释

    其实这道题算是一道相当标准(简单)的cf数据结构题,但是自己也是菜,上来就奔着模拟去了,写了个线段树,还一直wa。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #define max(a,b) (a>b)?a:b
    #define min(a,b) (a>b)?b:a
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    #define LL long long
    #define MAXN 300005
    const int maxn = 1000005;
    using namespace std;
    int n,q;
    long long qi;
    long long a[maxn];
    LL lazy[maxn<<2];
    LL sum[maxn<<2];
    void PushUp(int rt)//由左孩子、右孩子向上更新父节点
    {
    	sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    void PushDown(int rt,int m) //向下更新
    {
    	if (lazy[rt]!=-1) //懒惰标记
        {
    		lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
    		sum[rt<<1] = (m - (m >> 1)) * lazy[rt];
    		sum[rt<<1|1] = ((m >> 1)) * lazy[rt];
    		lazy[rt] = -1;
    	}
    }
    void build(int l,int r,int rt)//建树
    {
    	lazy[rt] = -1;
    
    	if (l== r)
    	{
            sum[rt]=a[l];
            //printf("%d %d\n",rt,sum[rt]);
            return ;
    	}
    	int m = (l + r) >> 1;
    	build(lson);
    	build(rson);
    	PushUp(rt);
    }
    void update(int L,int R,long long c,int l,int r,int rt)//更新
    {
        //if(L>l||R>r) return;
    	if (L <= l && r <= R)
        {
    		lazy[rt] = c;
    		sum[rt] = c * (r - l + 1);
    		return ;
    	}
    	PushDown(rt , r - l + 1);
    	int m = (l + r) >> 1;
    	if (L <= m) update(L , R , c , lson);
    	if (R > m) update(L , R , c , rson);
    	PushUp(rt);
    }
    LL query(int L,int R,int l,int r,int rt)
    {
    	if (L <= l && r <= R)
        {
            //printf("%d\n", sum[rt]);
    		return sum[rt];
    	}
    	PushDown(rt , r - l + 1);
    	int m = (l + r) >> 1;
    	LL ret = 0;
    	if (L <= m) ret += query(L , R , lson);
    	if (m < R) ret += query(L , R , rson);
    	return ret;
    }
    int check(int x)
    {
        if(query(1,x,1,n,1)<=qi)
        {
            return 0;
        }
        return 1;
    }
    void update1(int p,long long tihuan,int l,int r,int rt)
    {
        if (l == r) {
            sum[rt] = tihuan;
            return ;
        }
        int m = (l + r) >> 1;
        if (p <= m) update1(p , tihuan ,lson);
        else update1(p , tihuan , rson);
        PushUp(rt);
    }
    int solve(int flag)
    {
        if(query(1,n,1,n,1)<=qi)
        {
            build(1,n,1);
            return n;
        }
        int l=1,r=n,ans=-1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
           // printf("%d\n",mid);
            if(check(mid))
            {
                r=mid-1;
            }
            else
            {
                l=mid+1;
            }
        }
            long long tem=(qi-query(1,l,1,n,1));
            update1(l,-tem,1,n,1);
            //printf("B %d\n",tem);
            if(l>=2)
            {
                update(1,l-1,0,1,n,1);
            }
            return n-(l-1);
    }
    int main()
    {
        scanf("%d %d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        int flag=1;
        build(1,n,1);
        while(q--)
        {
            scanf("%lld",&qi);
            printf("%d\n",solve(flag++));
        }
    	return 0;
    }
    

    在第六个点wa了好久,后来才发现是因为我的区间修改lazy数组是用if(lazy[rt])更新的,也就是说如果lazy[rt]==0是不会更新的,但是lazy[rt]确实是我们要更新的状态=。=
    然后改了之后变成在第8个点tle了,线段树就算是无计可施了。
    仔细想想,其实这道题和codefroces948c是很像的,如果把雪堆看成勇士的话,二者都是每一回合削减某些,并且想要获取当前回合的信息。
    如果设a[i]为第1-i个勇士的总生命值,d[i]为1-i回合的总箭量,显然,在1-i名勇士中做一个二分搜索即可,然后又因为所有勇士都倒下后会复活,那么如果搜索到的是勇士的末尾,就重置d。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=2e5+5;
    int n,q;
    ll a[N],k[N];
    int main()
    {
    	int i,j;
    	ll d;
    	scanf("%d%d",&n,&q);
    	for(i=0;i<n;i++) scanf("%I64d",a+i);
    	for(i=0;i<q;i++) scanf("%I64d",k+i);
    	for(i=1;i<n;i++) a[i]+=a[i-1];
    	d=0;
    	for(i=0;i<q;i++){
    		d+=k[i];
    		j=upper_bound(a,a+n,d)-a;
    		if(j==n) d=j=0;
    		printf("%d\n",n-j);
    	}
    	return 0;
    }
    
    少女が見た日本の原風景
  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/SoniciSika/p/8983602.html
Copyright © 2011-2022 走看看