wjyi

人这么弱,有什么资格颓废(ಥ _ ಥ)

  博客园  :: 首页  :: 新随笔  :: 联系 ::  :: 管理

2016-05-28  10:27:19

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3343

比较显然的分块题,分块后块内排序,维护整块的附加信息add

对于操作来说,l,r所在的块暴力,其它块内直接加add,或二分查找大于某个值的数有多少个。

神奇WA

update:本傻叉的二分写法太过傻叉,卒于tmp没有赋初值

 1 #include<bits/stdc++.h>
 2 #define inf 1000000000
 3 #define N 1000005
 4 #define ll long long
 5 using namespace std;
 6 int read(){
 7   int x=0,f=1;char ch=getchar();
 8   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 9   while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
10   return x*f;
11 }
12 int n,q,m,block,a[N],b[N],pos[N],add[N];
13 void reset(int x){
14   int l=(x-1)*block+1,r=min(x*block,n);
15   for(int i=l;i<=r;i++)b[i]=a[i];
16   sort(b+l,b+r+1);
17 }
18 void update(int x,int y,int v){
19   if(pos[x]==pos[y]){
20     for(int i=x;i<=y;i++)a[i]+=v;
21   }
22   else{
23     for(int i=x;i<=pos[x]*block;i++)a[i]+=v;
24     for(int i=(pos[y]-1)*block+1;i<=y;i++)a[i]+=v;
25   }
26   reset(pos[x]);reset(pos[y]);
27   for(int i=pos[x]+1;i<pos[y];i++)add[i]+=v;
28 }
29 int find(int x,int v){
30   int l=(x-1)*block+1,r=min(x*block,n),last=r,mid,tmp=r+1;
31   while(l<=r){
32     mid=l+r>>1;
33     if(b[mid]>=v)tmp=mid,r=mid-1;
34     else l=mid+1;
35   }
36   return last-tmp+1;
37 }
38 int query(int x,int y,int v){
39   int sum=0;
40   if(pos[x]==pos[y]){
41     for(int i=x;i<=y;i++)if(a[i]+add[pos[x]]>=v)sum++;
42   }
43   else{
44     for(int i=x;i<=pos[x]*block;i++)
45       if(a[i]+add[pos[x]]>=v)sum++;
46     for(int i=(pos[y]-1)*block+1;i<=y;i++)
47       if(a[i]+add[pos[y]]>=v)sum++;
48   }
49   for(int i=pos[x]+1;i<pos[y];i++)
50     sum+=find(i,v-add[i]);
51   return sum;
52 }
53 int main(){
54   n=read();q=read();
55   block=(int)sqrt(n);
56   for(int i=1;i<=n;i++){
57     a[i]=read();
58     pos[i]=(i-1)/block+1;
59     b[i]=a[i];
60   }
61   if(n%block)m=n/block+1;
62   else m=n/block;
63   for(int i=1;i<=m;i++)reset(i);
64   for(int i=1;i<=q;i++){
65     char ch[5];
66     scanf("%s",ch);
67     int x=read(),y=read(),v=read();
68     if(ch[0]=='M')update(x,y,v);
69     else printf("%d\n",query(x,y,v));
70   }
71   return 0;
72 }
View Code

 

3343: 教主的魔法

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 984  Solved: 430
[Submit][Status][Discuss]

Description

教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N
每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[LR](1≤LRN)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第LR)个英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [LR] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
WD巨懒,于是他把这个回答的任务交给了你。
 

Input

       第1行为两个整数NQQ为问题数与教主的施法数总和。
       第2行有N个正整数,第i个数代表第i个英雄的身高。
       第3到第Q+2行每行有一个操作:
(1)       若第一个字母为“M”,则紧接着有三个数字LRW。表示对闭区间 [LR] 内所有英雄的身高加上W
(2)       若第一个字母为“A”,则紧接着有三个数字LRC。询问闭区间 [LR] 内有多少英雄的身高大于等于C
 

Output

       对每个“A”询问输出一行,仅含一个整数,表示闭区间 [LR] 内身高大于等于C的英雄数。
 

Sample Input

5 3
1 2 3 4 5
A 1 5 4
M 3 5 1
A 1 5 4

Sample Output

2
3

HINT

 

【输入输出样例说明】

原先5个英雄身高为1、2、3、4、5,此时[1, 5]间有2个英雄的身高大于等于4。教主施法后变为1、2、4、5、6,此时[1, 5]间有3个英雄的身高大于等于4。

 

【数据范围】

对30%的数据,N≤1000,Q≤1000。

对100%的数据,N≤1000000,Q≤3000,1≤W≤1000,1≤C≤1,000,000,000。

 

posted on 2016-05-28 10:31  wjyi  阅读(135)  评论(0编辑  收藏  举报