HDU 6315 Naive Operations 线段树+lazy标记

Naive Operations

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Others)
Total Submission(s): 2951    Accepted Submission(s): 1303


 

Problem Description

In a galaxy far, far away, there are two integer sequence a and b of length n.
b is a static permutation of 1 to n. Initially a is filled with zeroes.
There are two kind of operations:
1. add l r: add one for al,al+1...ar
2. query l r: query ∑ri=lai/bi

 

Input

There are multiple test cases, please read till the end of input file.
For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
In the second line, n integers separated by spaces, representing permutation b.
In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
1≤n,q≤100000, 1≤lrn, there're no more than 5 test cases.

 

Output

Output the answer for each 'query', each one line.

 

Sample Input

 

5 12 1 5 2 4 3 add 1 4 query 1 4 add 2 5 query 2 5 add 3 5 query 1 5 add 2 4 query 1 4 add 2 5 query 2 5 add 2 2 query 1 5

 

Sample Output

 

1 1 2 4 4 6

 

Source

2018 Multi-University Training Contest 2

题意:给你一个数组a起始全为0,和一个数组b有固定的值并为1到n的全排列,然后可以在一个区间(l,r)内给a[i]+1,或者询问一个区间内\sum[a[i]/b[i]];

思路:当时做的的时候怎么也没想到怎么用线段树更新,最后讲题的时候奆佬说(1/n+2/n+3/n+....+n/n)是调和级数每个点最多更新nlog(n)次,这样的复杂度完全可以接受巴拉巴拉的。打完好久我才把这道题补了,最开始的时候别人说的,用线段树录区间内最小的,每更新一次把最小的减1,直到减为0 了就ans++,然后把这个值赋为原来的b[i]继续更新,然后在记录一下最小值来自左边还是右边,以便判断是更新到这里就return还是更新左儿子,右儿子,还是都更新。其实只要你线段树的基础足够好,根本没有这么多操作,不记录最小的来自那边,更新的时候直接更新到最小值大于1或等于1的那个点在return就好,遇到最小值大于一的lazy加1,mi减1,当前点lazy不为0的直接推到左右儿子,查询的时候只要在节点的区间内直接返回ans就好了。

收获:比赛的时候想到了用线段树更新,不过怎么也没想到用线段树怎么更新 ,最后自己冷静下来慢慢思考最后终于还是AC了有些题,自己认真思考完全是可以做出来的,有些时候看博客反而效果不好,因为每个人的思维都是有差距的,看懂别人的代码就得明白别人的思路,这是一件十分痛苦的事,自己独立冷静严密的思考才是最重要的,线段树博大精深,完全掌握还有很长的路要走啊!

#include<stdio.h>
#include<string.h>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#define ll long long
#define qq printf("QAQ\n");
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const ll linf=8e18+9e17;
const int mod=1e9+7;
const double e=exp(1.0);
const double pi=acos(-1);
struct tree{
	int l,r,data,lazy,mi,ans,f;
}t[maxn<<2];
int a[maxn],b[maxn];
void pushup(int rt)
{
	t[rt].ans=t[rt<<1].ans+t[rt<<1|1].ans;
	
	t[rt].mi=min(t[rt<<1].mi,t[rt<<1|1].mi);
	
	if(t[rt<<1].mi>t[rt<<1|1].mi)t[rt].f=1;//最开始的思路 标记最小的来自哪里 后面没有用到
	else if(t[rt<<1].mi==t[rt<<1|1].mi)t[rt].f=0;
	else t[rt].f=-1;
}
void updata_lazy(int l,int r,int rt)
{
	if(l<=t[rt].l&&t[rt].r<=r)
	{
		if(t[rt].mi>1){//当前节点区间内的最小值比1大   
			t[rt].lazy++;
			t[rt].mi--;
			return ;
		}
		if(t[rt].mi==1&&t[rt].l==t[rt].r)//更新到底了 
		{
			t[rt].ans++;
			t[rt].mi=t[rt].data;
			t[rt].lazy=0;
			return ;
		}
	}
	if(t[rt].lazy){//吧lazy mi推到左右儿子 
		t[rt<<1].lazy+=t[rt].lazy;
		t[rt<<1|1].lazy+=t[rt].lazy;
		t[rt<<1].mi-=t[rt].lazy;
		t[rt<<1|1].mi-=t[rt].lazy;
		t[rt].lazy=0;
	}
	int mid=(t[rt].l+t[rt].r)>>1;
	if(mid>=r)updata_lazy(l,r,rt<<1);
	else if(mid<l)updata_lazy(l,r,rt<<1|1);
	else updata_lazy(l,mid,rt<<1),
	updata_lazy(mid+1,r,rt<<1|1);
	pushup(rt);
}
void build(int l,int r,int rt)
{
	t[rt].l=l;
	t[rt].r=r;
	t[rt].lazy=0;
	t[rt].ans=0;
	t[rt].mi=0;
	if(l==r){
		scanf("%d",&t[rt].data);
		t[rt].mi=t[rt].data;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	pushup(rt);
}
int query(int l,int r,int rt)
{
	if(l<=t[rt].l&&t[rt].r<=r)//已经更新好了直接还回就好 
	{
			return t[rt].ans;

	}
	if(t[rt].lazy){
		t[rt<<1].lazy+=t[rt].lazy;
		t[rt<<1|1].lazy+=t[rt].lazy;		
		t[rt<<1].mi-=t[rt].lazy;
		t[rt<<1|1].mi-=t[rt].lazy;
		t[rt].lazy=0;
	}
	int ans,mid=(t[rt].l+t[rt].r)>>1;
	if(r<=mid) ans=query(l,r,rt<<1);
	else if(l>mid)ans=query(l,r,rt<<1|1);
	else ans=query(l,mid,rt<<1)+
	query(mid+1,r,rt<<1|1);
	pushup(rt);
	return ans;
}
int main()
{
	int n,q,l,r;
	char s[20];
	while(scanf("%d%d",&n,&q)!=EOF)
	{
		build(1,n,1);
		while(q--)
		{
			scanf("%s",s);
			scanf("%d%d",&l,&r);
			if(s[0]=='a')updata_lazy(l,r,1);
			else printf("%d\n",query(l,r,1));
		}
	}
	return 0;
}
/*
5 12
1 5 2 4 3
add 1 5
query 1 5
add 1 5
query 1 5
add 1 5
query 1 5
add 1 5
query 1 5
add 1 5
query 1 5
add 1 5
query 1 5
*/

猜你喜欢

转载自blog.csdn.net/swust5120166213/article/details/81502845