3.22

线段树

如果相邻两个颜色均相同则删除当前颜色

thinking

经典题目有毒,读懂题目后,知道只需要对每一个相邻的三元素判定是否相同,进行按需要进行删除即可。

solution

class Solution {
public:
    bool winnerOfGame(string& c) {
        int n=c.size();
        int a=0;int b=0;
        for(int i=0;i<=n-3;++i) {
            if(c[i]==c[i+1]&&c[i+1]==c[i+2]) {
                if(c[i]=='A') ++a;
                else ++b;
            }
        }
        return a>b;
    }
};

带标记的线段树

thinking

接着昨天的线段树来说,此题考虑到区间修改,我们不能在进行循环进行修改,因此我们需要改进一下线段树,我们引入一般的标记方法。

我们引入用来标记的树(数组V)对区间的更改进行适当地记录,具体方法如下:(我们不去证明该种方法地合理性)

  • 插入

对于修改的区间\([l,r]\),我们将f,v对照着进行观看,从两者的根节点出发,寻找完美契合的区间,对于v,完美契合的区间,我们加上更新的差值,路径上的节点不去管理,对于f,从根节点到契合的区间端点,契合的端点处,我们不去管。路径上的节点值增加对应的区间的变动值。

  • 查询

由于我们的插入方法,对于给定查询区间\([l,r]\),进而在两棵树上寻找对应的变动值,对于任意的查询区间来说,如果出现了完美契合,那么值就是根节点到当前区间的v值*区间长度+f[k],我们思考为什么是根节点到当前契合区间的路径的v的总和。从v的更新来看,每一次的区间更新,我们将区间落下,分成几段完全契合的片段,更新v值,当增大区间的时候,这部分的更新至就有可能落在上面,同时对该区间起到了修改作用,因此,需要遍历求和整条路经。

反过来,我们观察f,f始终更新的是大段的值(非契合区间),这样,v与f的结合使用,就解决了区间修改的问题。

solution

const int N=1e5+1;
int n,m;long long a[N],f[4*N],v[4*N];

inline void buildtree(int k,int l,int r) {
	v[k]=0;
	if(l==r) {
		f[k]=a[l];
		return;
	}
	int m=(l+r)>>1;
	buildtree(k+k,l,m);
	buildtree(k+k+1,m+1,r);
	f[k]=f[k+k]+f[k+k+1];
}

inline void insert(int k,int l,int r,int x,int y,long long z) {
	if(l==x&&r==y) {
		v[k]+=z;
		return;
	}
	f[k]+=(y-x+1)*z;
	int m=(r+l)>>1;
	if(y<=m)
		insert(k+k,l,m,x,y,z);
	else
		if(x>m)
			insert(k+k+1,m+1,r,x,y,z);
		else
			insert(k+k,l,m,x,m,z),
			insert(k+k+1,m+1,r,m+1,y,z);
}

long long calc(int k,int l,int r,int x,int y,long long p) {
	p+=v[k];
	if(l==x&&y==r) {
		return p*(r-l+1)+f[k];
	}
	int m=(l+r)>>1;
	if(y<=m)
		return calc(k+k,l,m,x,y,p);
	else
		if(x>m)
			return calc(k+k+1,m+1,r,x,y,p);
		else
			return calc(k+k,l,m,x,m,p)+calc(k+k+1,m+1,r,m+1,y,p);
}

void solve() {
	cin>>n>>m;
	for(int i=1;i<=n;++i) cin>>a[i];
	buildtree(1,1,n);
	for(int i=0;i<m;++i) {
		int index;cin>>index;
		if(index==1) {
			int x,y;cin>>x>>y;long long k;cin>>k;
			insert(1,1,n,x,y,k);	
		} else {
			int x,y;cin>>x>>y;
			cout<<calc(1,1,n,x,y,0)<<'\n';
		}
	}
}
posted @ 2022-03-23 00:57  圣道  阅读(154)  评论(0)    收藏  举报