HDU6315 Naive Operations(多校第二场1007)(线段树)

Naive Operations

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

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=l⌊ai/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≤l≤r≤n, 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

题目大意:b[1-n] 是 1-n  ,a[1-n] 是 0,add区间每一数加1,query区间a[i]/b[i]的和

思路:维护区间最小值,add操作为b[l]~b[r] 减一,最小值为0说明某个位置a[i]/b[i]=1, 答案贡献1,最后求区间和即可

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <math.h>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <string>
  7 #include <vector>
  8 #include <set>
  9 #include <map>
 10 #include <queue>
 11 #include <algorithm>
 12 #include <sstream>
 13 #include <stack>
 14 using namespace std;
 15 #define rep(i,a,n) for (int i=a;i<n;i++)
 16 #define per(i,a,n) for (int i=n-1;i>=a;i--)
 17 #define pb push_back
 18 #define mp make_pair
 19 #define all(x) (x).begin(),(x).end()
 20 #define fi first
 21 #define se second
 22 #define SZ(x) ((int)(x).size())
 23 #define FO freopen("in.txt", "r", stdin);
 24 #define debug(x) cout << "&&" << x << "&&" << endl;
 25 #define lowbit(x) (x&-x)
 26 #define mem(a,b) memset(a, b, sizeof(a));
 27 typedef vector<int> VI;
 28 typedef long long ll;
 29 typedef pair<int,int> PII;
 30 const ll mod=1000000007;
 31 const int inf = 0x3f3f3f3f;
 32 ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
 33 ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
 34 //head
 35
 36 const int N=100010;
 37 int b[N];
 38 int sum[N<<2],sub[N<<2],lazy[N<<2];//区间和  区间最小值 lazy标记
 39
 40 void Pushup(int rt) {//上传
 41     sum[rt]=sum[rt<<1]+sum[rt<<1|1];//左右孩子之和
 42     sub[rt]=min(sub[rt<<1],sub[rt<<1|1]);//左右孩子的最小值
 43 }
 44
 45 void Pushdown(int rt) {//下压
 46     lazy[rt<<1]+=lazy[rt];//传标记
 47     lazy[rt<<1|1]+=lazy[rt];
 48     sub[rt<<1]-=lazy[rt];//更新 因为是每次减一 所以就直接减lazy
 49     sub[rt<<1|1]-=lazy[rt];
 50     lazy[rt]=0;//清除父节点标记
 51 }
 52
 53 void build(int rt,int L,int R) {
 54     sum[rt]=0;//rt的初始状态
 55     lazy[rt]=0;
 56     if(L==R) {
 57         scanf("%d",&b[L]);//建树的一种方式
 58         sub[rt]=b[L];
 59         return;
 60     }
 61     int mid=(L+R)>>1;//递归建树
 62     build(rt<<1,L,mid);
 63     build(rt<<1|1,mid+1,R);
 64     Pushup(rt);//因为不涉及修改,不需要下压,只需上传
 65 }
 66
 67 void dfs(int rt,int L,int R) {
 68     if(L==R) {
 69         sum[rt]++;
 70         sub[rt]=b[L];
 71         return;
 72     }
 73     int mid=(L+R)>>1;
 74     Pushdown(rt);
 75     if(!sub[rt<<1]) dfs(rt<<1,L,mid);
 76     if(!sub[rt<<1|1]) dfs(rt<<1|1,mid+1,R);
 77     Pushup(rt);
 78 }
 79
 80 void Updata(int rt,int L,int R,int l,int r) {//L,R为时时变动的区间
 81     if(L>=l&&R<=r) {//如果当前节点在待查询节点内
 82         lazy[rt]++;
 83         sub[rt]--;
 84         if(!sub[rt]) dfs(rt,L,R);//如果区间最小值为0,递归搜索位置
 85         return;
 86     }
 87     int mid=(L+R)>>1;//递归找l,r的涉及区间
 88     Pushdown(rt);//需要走左右孩子,先下压
 89     if(l<=mid) Updata(rt<<1,L,mid,l,r);
 90     if(r>mid) Updata(rt<<1|1,mid+1,R,l,r);
 91     Pushup(rt);//走完之后,状态上传给父亲节点
 92 }
 93
 94 int Query(int rt,int L,int R,int l,int r) {
 95     if(L>=l&&R<=r) //待查询区间内
 96         return sum[rt];
 97     int mid=(L+R)>>1;
 98     Pushdown(rt);//走左右孩子
 99     int ans=0;
100     if(l<=mid) ans+=Query(rt<<1,L,mid,l,r);
101     if(r>mid) ans+=Query(rt<<1|1,mid+1,R,l,r);
102     Pushup(rt);//走完,状态上传给父亲节点
103     return ans;
104 }
105
106
107 int main() {
108     int n,q;
109     while(~scanf("%d%d",&n,&q)) {
110         build(1,1,n);
111         char s[10];
112         int a,b;
113         while(q--) {
114             scanf("%s%d%d",s,&a,&b);
115             if(s[0]==‘a‘) Updata(1,1,n,a,b);
116             else printf("%d\n",Query(1,1,n,a,b));
117         }
118     }
119 }

上面用了dfs搜索最小值为0的位置,也可以一直去找。

 1 void Update(int L,int R,int l,int r,int rt)
 2 {
 3     if(a[rt]>1&&L<=l&&r<=R)
 4     {
 5         lazy[rt]++;
 6         a[rt]--;
 7         return;
 8     }
 9     if(a[rt]==1&&l==r)
10     {
11         sum[rt]++;
12         lazy[rt]=0;
13         a[rt]=b[l];
14         return;
15     }
16     int mid=(l+r)>>1;
17     PushDown(rt);
18     if(L<=mid)Update(L,R,l,mid,rt<<1);
19     if(R>mid)Update(L,R,mid+1,r,rt<<1|1);
20     PushUp(rt);
21 }

!!!!这里的变量含义和第一个代码不一样。自行理解。

原文地址:https://www.cnblogs.com/ACMerszl/p/9741223.html

时间: 2024-11-12 04:31:59

HDU6315 Naive Operations(多校第二场1007)(线段树)的相关文章

多校第二场 简单排序计算

思路:先按交叉相乘之差排序好了计算就行了. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <map> #include <cstdlib> #include <queue> #include <stack> #include <vector> #include <ctype.

2018 hdu 多校 第二场

因为3点半才来(其实是3点50,刚刚到酒店就开始了= =队友也是一个那时刚刚睡醒= = 1004 小甜甜 全部yes就好了 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 #include <vector> 6 #include <queue> 7 #include <set> 8 #include

2018-3-17-湖南多校第二场

湖南多校第2场 A:太水 队友直接秒了 C: Hedwig's Ladder 队友打了个表,然后一眼规律 类似于斐波拉契 1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <cmath> 5 #include <algorithm> 6 #include <set> 7 #include <iostream> 8 #include

hdu_6055 : Regular polygon (2017 多校第二场 1011) 【计算几何】

题目链接 有个结论: 平面坐标系上,坐标为整数的情况下,n个点组成正n边形时,只可能组成正方形. 然后根据这个结论来做. 我是先把所有点按照 x为第一关键字,y为第二关键字 排序,然后枚举向量 (p[i]->p[j]) (j>i),只判断这个向量左侧可否存在两个点与它一起构成一个正方形.这样算的结果是,计数每个正方形时,它的靠右和靠下的两条边都会为ans贡献一个单位,所以最后ans要除以2. #include<bits/stdc++.h> using namespace std;

HDU 5294 多校第一场1007题 最短路+最小割

Tricks Device Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1285    Accepted Submission(s): 302 Problem Description Innocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu’s at the ent

hdu_6050: Funny Function (2017 多校第二场 1006) 【找规律】

题目链接 暴力打个表找下规律就好了,比赛时看出规律来了倒是,然而看这道题看得太晚了,而且高中的那些数列相关的技巧生疏了好多,然后推公式就比较慢..其实还是自身菜啊.. 公式是 #include<bits/stdc++.h> using namespace std; typedef long long LL; const LL mod=1e9+7; LL qpow(LL x,LL n) //求x^n%mod { LL ret=1; for(; n; n>>=1) { if(n&

hdu 5305 Friends(2015多校第二场第6题)记忆化搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5305 题意:给你n个人,m条关系,关系可以是online也可以是offline,让你求在保证所有人online关系的朋友和offline关系的朋友相等的情况下,这样的情况有多少种. 思路:因为online关系和offline关系的人数相等,而且m最多才28,所以只要枚举每个人的一半的关系是否符合要求即可,而且根据题意m是奇数或者有一个人的总关系为奇数那么就没有符合要求的情况,这样可以排除很多情况.

2015多校第二场 1004( Delicious Apples )

题意:有一条圆形的路,你的仓库在0点,这条路长l,然后有n个苹果树,每个数的坐标是xi(顺时针),每棵树上有ai个苹果.你有个篮子,能装k个苹果,问你用这个篮子将所有苹果装回仓库所走的最短路为多少? 1≤n,k≤105,ai≥1,a1+a2+...+an≤105 1≤L≤109 0≤x[i]≤L 请特别注意上面的苹果个数的条件.因为我的学长 就是从这个条件成功做出了这道题,orz! 因为苹果数不超过10^5,所以将每个苹果当作点. 用一个数组pos记录每个苹果距0点的距离,排序后,然后就可以用另

多校第二场 1004 hdu 5303 Delicious Apples(背包+贪心)

题目链接: 点击打开链接 题目大意: 在一个周长为L的环上.给出n棵苹果树.苹果树的位置是xi,苹果树是ai,苹果商店在0位置,人的篮子最大容量为k,问最少做多远的距离可以把苹果都运到店里 题目分析: 首先我们能够(ˇ?ˇ) 想-,假设在走半圆之内能够装满,那么一定优于绕一圈回到起点.所以我们从中点将这个圈劈开.那么对于每一个区间由于苹果数非常少,所以能够利用belong[x]数组记录每一个苹果所在的苹果树位置,然后将苹果依照所在的位置排序,那么也就是我们知道每次拿k个苹果的代价是苹果所在的最远