zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:Weed(线段树)

    题目描述

    $duyege$的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹。
    为了查出真相,$duyege$准备修好电脑之后再进行一次金坷垃的模拟实验。
    电脑上面有若干层金坷垃,每次只能在上面撒上一层高度为$v_i$的金坷垃,或者除掉最新$v_i$层(不是量)撒的金坷垃。如果上面只留有不足$v_i$层金坷垃,那么就相当于电脑上面没有金坷垃了。
    $duyege$非常严谨,一开始先给你$m$个上述操作要你依次完成。然后又对实验步骤进行了$q$次更改,每次更改都会改变其中一个操作为另外一个操作。每次修改之后都会询问最终金坷垃的量有多少。


    输入格式

    输入第一行为两个正整数$m$、$q$,接下来$m$行每行$2$个整数$k$、$v_i$。$k$为$0$时撒金坷垃,为$1$时除金坷垃。接下来$q$行每行$3$个整数$c_i$、$k$、$v_i$,$c_i$代表被更改的操作是第$c_i$个,后面$2$个数描述更改为这样的操作。


    输出格式

    输出$q$行代表每次金坷垃的量为多少。


    样例

    样例输入

    10 5
    0 10
    1 5
    0 13
    0 18
    0 2
    1 1
    0 8
    0 9
    1 3
    0 7
    9 0 3
    10 1 7
    6 0 8
    10 0 5
    8 1 2

    样例输出

    58
    0
    0
    66
    41


    数据范围与提示

    对于$30%$的数据$mleqslant 1,000,qleqslant 1,000$。
    对于另外$20%$的数据,每次$k=1$时都会将金坷垃清空。
    对于$100%$的数据,$mleqslant 2 imes {10}^5,qleqslant 2 imes {10}^5,v_ileqslant {10}^4$。


    题解

    首先,来解释一下题意,在更改操作之后就不改回来啦。

    $30%$算法:

    暴力修改,每次都暴力扫一遍统计答案。

    时间复杂度:$Theta(m imes q)$。

    期望得分:$30$分。

    实际得分:$30$分。

    $100%$算法:

    利用线段树维护以下四个值:

    $alpha.$区间内加数总和$sum$。

    $eta.$当前区间向前删除数字的数量$del$。

    $gamma.$当前区间内“净”加的元素数$add$。

    $delta.$当前区间被右兄弟删除后的总和$fla$(只对左儿子维护这个信息即可)。

    每次询问就是输出$sum[1]$。

    之后就是代码实现的问题了,主要是$pushup$函数比较难搞。

    时间复杂度:$Theta(Nlog N+Qlog^2N)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    $30%$算法:

    #include<bits/stdc++.h>
    using namespace std;
    int m,q;
    pair<bool,int> e[200001];
    int sta[200001],top;
    int ans;
    int main()
    {
    	scanf("%d%d",&m,&q);
    	for(int i=1;i<=m;i++)
    		scanf("%d%d",&e[i].first,&e[i].second);
    	while(q--)
    	{
    		ans=0;
    		top=0;
    		int c,k,v;
    		scanf("%d%d%d",&c,&k,&v);
    		e[c]=make_pair(k,v);
    		for(int i=1;i<=m;i++)
    			if(e[i].first==1)for(int j=1;j<=e[i].second;j++)if(top)top--;else break;
    			else sta[++top]=e[i].second;
    		for(int i=1;i<=top;i++)ans+=sta[i];
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    $100%$算法:

    #include<bits/stdc++.h>
    #define L(x) x<<1
    #define R(x) x<<1|1
    using namespace std;
    int m,q;
    int c,k,v;
    pair<bool,int> e[200001];
    int tradd[1000000],trdel[1000000],trfla[1000000],trsum[1000000];
    int ask(int x,int w)
    {
    	if(w<tradd[R(x)])return trfla[L(x)]+ask(R(x),w);
    	if(w==tradd[R(x)])return trfla[L(x)];
    	if(w>tradd[R(x)])return ask(L(x),w-tradd[R(x)]+trdel[R(x)]);
    }
    void pushup(int x)
    {
    	if(tradd[L(x)]<=trdel[R(x)])
    	{
    		trfla[L(x)]=0;
    		tradd[x]=tradd[R(x)];
    		trdel[x]=trdel[L(x)]+trdel[R(x)]-tradd[L(x)];
    		trsum[x]=trsum[R(x)];
    	}
    	else
    	{
    		if(trdel[R(x)])trfla[L(x)]=ask(L(x),trdel[R(x)]);
    		else trfla[L(x)]=trsum[L(x)];
    		tradd[x]=tradd[L(x)]+tradd[R(x)]-trdel[R(x)];
    		trdel[x]=trdel[L(x)];
    		trsum[x]=trfla[L(x)]+trsum[R(x)];
    	}
    }
    void build(int x,int l,int r)
    {
    	if(l==r)
    	{
    		if(e[l].first)trdel[x]=e[l].second;
    		else
    		{
    			tradd[x]=1;
    			trsum[x]=e[l].second;
    			trfla[x]=e[l].second;
    		}
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(L(x),l,mid);
    	build(R(x),mid+1,r);
    	pushup(x);
    }
    void clear(int x){tradd[x]=trdel[x]=trsum[x]=trfla[x]=0;}
    void change(int x,int l,int r,int w)
    {
    	if(l==r)
    	{
    		clear(x);
    		if(e[l].first)trdel[x]=e[l].second;
    		else
    		{
    			tradd[x]=1;
    			trsum[x]=e[l].second;
    			trfla[x]=e[l].second;
    		}
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(w<=mid)change(L(x),l,mid,w);
    	else change(R(x),mid+1,r,w);
    	pushup(x);
    }
    int main()
    {
    	scanf("%d%d",&m,&q);
    	for(int i=1;i<=m;i++)
    		scanf("%d%d",&e[i].first,&e[i].second);
    	build(1,1,m);
    	while(q--)
    	{
    		scanf("%d%d%d",&c,&k,&v);
    		e[c]=make_pair(k,v);
    		change(1,1,m,c);
    		printf("%d
    ",trsum[1]);
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    【天梯 L2-008 最长对称子串 】 最长回文子串 manacher
    【天梯L2-001 城市间紧急救援】 双关键字最短路+记录路径 堆优化Dijkstra
    记录板

    留言板
    使用 Docker 搭建 Java Web 运行环境(转)
    数据库隔离级别和锁
    线程上下文类加载
    tomcat是怎么找到项目lib目录下的jar包的,求大神解答
    Java中try、finally语句中有return时的执行情况 [转]
  • 原文地址:https://www.cnblogs.com/wzc521/p/11335541.html
Copyright © 2011-2022 走看看