lightoj1135(线段树 + 延迟标记)

思路:题目就是0 ~ n - 1个数,m次操作,往区间添加1或者查询区间有多少个可以被3整除的数;

被三整除的余数就是0,1,2。如果添加1就变换三个数的值;

点击题目链接

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2015
File Name   :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
using namespace std;
#define MEM(a,b) memset(a,b,sizeof a)
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
inline int Readint(){
	char c = getchar();
	while(!isdigit(c)) c = getchar();
	int x = 0;
	while(isdigit(c)){
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x;
}
const int maxn = 1e5 + 10;
int m1[maxn << 2],m2[maxn << 2],m0[maxn << 2];
int add[maxn << 2];
void change(int rt,int op){
	if (op == 0) return ;
	int a = m0[rt];
	int b = m1[rt];
	int c = m2[rt];
	if (op == 1){
		m0[rt] = c;m1[rt] = a;m2[rt] = b;
		return ;
	}
	else {
		m0[rt] = b;m1[rt] = c;m2[rt] = a;
		return ;
	}
}
void up(int rt){
	m0[rt] = m0[rt << 1] + m0[rt << 1 | 1];
	m1[rt] = m1[rt << 1] + m1[rt << 1 | 1];
	m2[rt] = m2[rt << 1] + m2[rt << 1 | 1];
}
void down(int rt){
	if (add[rt]){
		add[rt << 1] += add[rt];
		add[rt << 1 | 1] += add[rt];
		change(rt << 1,add[rt] % 3);
		change(rt << 1 | 1,add[rt] % 3);
		add[rt] = 0;
	}
}
void built(int L,int R,int rt){
	m1[rt] = m2[rt] = m0[rt] = 0;
	add[rt] = 0;
	if (L == R){
		m0[rt] = 1;
		return ;
	}
	int mid = (L + R) >> 1;
	built(L,mid,rt << 1);
	built(mid + 1,R,rt << 1 | 1);
	up(rt);
}
void updata(int L,int R,int rt,int l,int r){
	if (l <= L && R <= r){
		add[rt]++;
		int a = m0[rt];
		int b = m1[rt];
		int c = m2[rt];
		m0[rt] = c;
		m1[rt] = a;
		m2[rt] = b;
		return ;
	}
	down(rt);
	int mid = (L + R) >> 1;
	if (l <= mid) updata(L,mid,rt << 1,l,r);
	if (r > mid) updata(mid + 1,R,rt << 1 | 1,l,r);
	up(rt);
}
int Query(int L,int R,int rt,int l,int r){
	if (l <= L && R <= r) return m0[rt];
	int mid = (L + R) >> 1;
	down(rt);
	int res = 0;
	if (l <= mid) res += Query(L,mid,rt << 1,l,r);
	if (r > mid) res += Query(mid + 1,R,rt << 1 | 1,l,r);
	up(rt);
	return res;
}
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	int icase = 0;
	int t;
	scanf("%d",&t);
	while(t--){
		printf("Case %d:\n",++icase);
		int n,Q;
		scanf("%d%d",&n,&Q);
		built(0,n - 1,1);
		int a,b,c;
		for (int i = 1;i <= Q;i++){
			scanf("%d%d%d",&a,&b,&c);
			if (a == 0){
				updata(0,n - 1,1,b,c);
			}
			else printf("%d\n",Query(0,n - 1,1,b,c));
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值