2018 Multi-University Training Contest 2(Naive Operations ) hdu6315

题目连接:Naive Operations

题意,两个数组,一个a[]开始全为0,一个b[]为一个1~n的排列,有两种操作,把[L,R]的a全加1,第二种询问区间[L,R]a[i]/b[i]的和

题解:开一个线段树,最开始为b[i],维护最小值还有位置(有多个最小之时先保存最左边的),每一次更新都对范围的值-1,然后再开个树状数组保存答案,当某个位置 为0时这个位置就可以加1,然后重新置为b[i];,为什么这样不会超时呢(因为总共的操作n=1e5,n/1+n/2+n/2+....n/n,是个调和级数复杂度为nlogn)

  1 #include<bits/stdc++.h>
  2 #include<set>
  3 #include<cstdio>
  4 #include<iomanip>
  5 #include<iostream>
  6 #include<string>
  7 #include<cstring>
  8 #include<algorithm>
  9 #define pb push_back
 10 #define mk make_pair
 11 #define ll long long
 12 #define fi first
 13 #define se second
 14 #define PI 3.14159265
 15 #define ls l,m,rt<<1
 16 #define rs m+1,r,rt<<1|1
 17 #define eps 1e-7
 18 #define pii pair<int,int>
 19 typedef unsigned long long ull;
 20 const int mod=1e3+5;
 21 const ll inf=0x3f3f3f3f3f3f3f;
 22 const int maxn=1e5+5;
 23 using namespace std;
 24 int n,q;
 25 int tr[maxn<<2],pos[maxn<<2],b[maxn],laz[maxn<<2],an[maxn];//最小值,最值位置
 26 int lowbit(int x){return x&(-x);}
 27 int add(int x,int val){while(x<=n)an[x]+=val,x+=lowbit(x);}
 28 int get_sum(int x)
 29 {
 30     int ans=0;
 31     while(x>0){ans+=an[x],x-=lowbit(x);}
 32     return ans;
 33 }
 34 int query(int l,int r){return get_sum(r)-get_sum(l-1);};
 35 void init(){memset(an,0,sizeof(an));}
 36 void push_up(int rt)
 37 {
 38     if(tr[rt<<1]<=tr[rt<<1|1])
 39     {
 40         tr[rt]=tr[rt<<1];pos[rt]=pos[rt<<1];
 41     }
 42     else
 43     {
 44         tr[rt]=tr[rt<<1|1];pos[rt]=pos[rt<<1|1];
 45     }
 46 }
 47 void push_down(int rt)
 48 {
 49     if(laz[rt]!=0)
 50     {
 51         laz[rt<<1]+=laz[rt];
 52         laz[rt<<1|1]+=laz[rt];
 53         tr[rt<<1]-=laz[rt];
 54         tr[rt<<1|1]-=laz[rt];
 55         laz[rt]=0;
 56     }
 57 }
 58 void built(int l,int r,int rt)
 59 {
 60     laz[rt]=0;
 61     if(l==r)
 62     {
 63         pos[rt]=l;
 64         tr[rt]=b[l];return ;
 65     }
 66     int m=(l+r)>>1;
 67     built(ls);built(rs);
 68     push_up(rt);
 69 }
 70 void update(int L,int R,int val,int l,int r,int rt)
 71 {
 72     if(L<=l&&r<=R)
 73     {
 74         tr[rt]-=val;
 75         laz[rt]+=val;return ;
 76     }
 77     push_down(rt);
 78     int m=(l+r)>>1;
 79     if(L<=m)update(L,R,val,ls);
 80     if(R>m) update(L,R,val,rs);
 81     push_up(rt);
 82 }
 83 pii query(int L,int R,int l,int r,int rt)
 84 {
 85     if(L<=l&&r<=R)
 86     {
 87         return mk(tr[rt],pos[rt]);
 88     }
 89     push_down(rt);
 90     int m=(l+r)>>1;pii ans;ans.fi=1e9;
 91     if(L<=m)ans=min(ans,query(L,R,ls));
 92     if(R>m)ans=min(ans,query(L,R,rs));
 93     return ans;
 94 }
 95 int main()
 96 {
 97     while(~scanf("%d %d",&n,&q))
 98     {
 99         init();
100         for(int i=1;i<=n;i++)scanf("%d",b+i);
101         built(1,n,1);
102         while(q--)
103         {
104             char op[100];int x,y;
105             scanf("%s %d %d",op,&x,&y);
106             if(op[0]==‘a‘)
107             {
108                 update(x,y,1,1,n,1);
109                 int l=x,r=y;
110                 while(l<=r)
111                 {
112                     pii tmp=query(l,r,1,n,1);
113                     if(tmp.fi==0)
114                     {
115                         update(tmp.se,tmp.se,-b[tmp.se],1,n,1);
116                         l=tmp.se+1;
117                         add(tmp.se,1);
118                     }
119                     else break;
120                 }
121             }
122             else
123             {
124                 printf("%d\n",query(x,y));
125             }
126         }
127     }
128     return 0;
129 }

原文地址:https://www.cnblogs.com/lhclqslove/p/9371275.html

时间: 2024-10-02 01:11:04

2018 Multi-University Training Contest 2(Naive Operations ) hdu6315的相关文章

HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)

http://acm.hdu.edu.cn/showproblem.php?pid=6315 题意 a数组初始全为0,b数组为1-n的一个排列.q次操作,一种操作add给a[l...r]加1,另一种操作query查询Σfloor(ai/bi)(i=l...r). 分析 真的是太naive啦,现场时没做出来. 看见区间自然想起线段树,那么这里的关键就是整除问题,只有达到一定数量才会对区间和产生影响. 反过来想,先把a[i]置为b[i],那么每次add时就是-1操作,当a[i]为0时区间和+1,再把

2018 Multi-University Training Contest 2 - Naive Operations

线段树 a数组一开始全是0,每次增加1,我们可以发现不一定每一个a[i]/b[i]都是会影响答案的. 也就是说,只有a[i]>b[i]才会影响答案,为了方便比较,我们可以把a的初始值变成b,然后每次区间加1相当于区间减1,当有某个数减为0,就代表影响了一次答案,我们可以暴力找到这个数,将他重置为b的初始值,然后更新答案. 对于没有影响答案的区间,只需要打标记,区间减1则让最小值减1即可. #include <bits/stdc++.h> #define INF 0x3f3f3f3f #d

2018 Nowcoder Multi-University Training Contest 2

Practice Link A. run 题意: 白云每次可以移动\(1\)米或者\(k\)米,询问移动的米数在\([L, R]\)范围内的方案数有多少. 思路: \(dp[i][2]\)表示到第\(i\)米,是通过\(1\)米的方式过来的还是\(k\)米的方式过来的,递推即可. 代码: #include <bits/stdc++.h> using namespace std; #define N 100010 const int p = 1e9 + 7; int f[N][2], g[N];

2018 Nowcoder Multi-University Training Contest 1

Practice Link J. Different Integers 题意: 给出\(n\)个数,每次询问\((l_i, r_i)\),表示\(a_1, \cdots, a_i, a_j, \cdots, a_n\)中有多少个不同的数. 思路: 先分别离线求出\(a_1, \cdots a_i\)以及\(a_j, \cdots, a_n\)中有多少个不同的数. 再考虑有多少个数既在\([1, i]\)中也在\([j, n]\)中,再离线做一次. 考虑一个数第一次出现的时候,那么这个数下一次出现

2018 Nowcoder Multi-University Training Contest 5

Practice Link A. gpa 题意: 有\(n\)门课程,每门课程的学分为\(s_i\),绩点为\(c_i\),要求最多删除\(k\)门课程,使得gpa最高. gpa计算方式如下: \[ \begin{eqnarray*} gpa = \frac{\sum s_ic_i}{\sum s_i} \end{eqnarray*} \] 思路: 首先删去的课程越多,gpa肯定不会变得更差. 所以我们肯定是删去\(k\)门课程. 考虑二分答案,check的时候要满足: \[ \begin{eq

Naive Operations HDU6315 (杭电多校2G)

让ci = ai / bi, 求sum(ci)的值,因为每次 ai 都是加一的,那么我可以用一颗线段树来维护每个 i 位置的 ai 距离达到 bi 还需要的数的最小值,更新是每次都减一,如果我某一个区间的最小值等于 0, 这就说明我这时候的ai已经满足了ai/bi==1的情况,那么对应的ci的位置就应该加一,所以我每次发现一个区间的最小值是0的话,我就 dfs 去找到为0的地方,把这里重新修改成bi,然后这个位置的答案+1就可以了 #include<map> #include<set&g

HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 5943    Accepted Submission(s): 2004 Problem Description Before

2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate 【DFS+剪枝+矩阵旋转】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6341 Problem J. Let Sudoku Rotate Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1363    Accepted Submission(s): 717 Problem Description Sudoku i

杭电2018多校第一场(2018 Multi-University Training Contest 1) 1001.Maximum Multiple (HDU6298)-数学思维题(脑子是个好东西,可惜我没有)

暑假杭电多校第一场,这一场是贪心场,很多贪心的题目,但是自己太菜,姿势挫死了,把自己都写吐了... 2018 Multi-University Training Contest 1 HDU6298.Maximum Multiple 题目意思就是给你一个n,找出来三个数x,y,z, 使得n=x+y+z,而且x,y,z都是n的因数,并且x*y*z为最大值,让你输出来x*y*z的最大值.如果没有满足条件的情况就输出-1. 由1=1/2+1/3+1/6=1/3+1/3+1/3=1/2+1/4+1/4,所