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;
    }
    
    少女が見た日本の原風景
  • 相关阅读:
    P4165 [SCOI2007]组队
    CF575B
    SG函数胡乱一气
    CF280C Game on Tree
    AGC010F
    CF140E
    多功能的低功耗蓝牙可穿戴设备用于监测血液酒精浓度
    智能手环幕后的英雄
    图像处理实用资源
    15.12DataGridView分页显示
  • 原文地址:https://www.cnblogs.com/SoniciSika/p/8983602.html
Copyright © 2011-2022 走看看