Problem G: Find the minimum
Time Limit: 2 Sec
Memory Limit: 128 MB
Submit: 60
Solved: 14
[ Submit][ Status][ Web Board]
Description
Given an integer array of size N, we define two kind of operators:
1. Add(L,R,W) : adding an integer W to every element in subarray[L,R];
2. Min(L,R) : returning the minimum number in subarray[L,R].
Note. L and R are the index of array starting from 0. L > R is possible. If L > R, the subarray is composed of array[L], array[L+1].....array[N-1], array[0], array[1],.....array[R].
Input
There are several test cases, processed to the end of file.
For each test, the first line contains two positive integers N and M. N is the size of array, and M is the number of the operation.
The second line contains N array elements, a1, a2, a3, ...., and an.
Then in the following M lines, each line contains an operation. If the line contains three integers L,R and W, it means the add(L,R,W) operator should be involved. If the line contains two integers L,R , it means the Min(L,R) operator should be involved.
(0<N, M<100,000; 0<= ai <= 10^6; 0 <= L, R <= N – 1, -10^6 <= W <= 10^6。)
Output
For each Min(L,R) operator in test case, output the return value.
Sample Input
3 31 2 40 20 0 10 2
Sample Output
12
HINT
the output value may be very large ,long long type is recommended!
给#define跪了。。。。
没想到被宏定义卡了一早上。。。
宏定义不是很快的样子么。。。
以后再也不乱用宏定义了。。。。
题目大意:给n个数,2种操作,第一种操作给一个区间,要查询该区间最小值,第二种操作给一个区间和一个值,给该区间所有数加上该值。注意区间0~n-1。如果给的区间r<l,则对0-r和l~n-1两个区间操作。
题目分析:这是今年地大邀请赛的G题。很裸的线段树。维护区间最小值,加一个lazy标记成段更新即可。比赛的时候顺利的1A了,今天听说挂出来了,顺便水一下,没想到跪了大半个早上。代码并不难写,关键是TLE。。。TLE?这不科学!然后就悲剧的从头到尾检查了n遍,提交了n遍,都是TLE。然后就各种手动优化输入,结果还是在超时的边缘徘徊。
然后突然看到有个求最小值的Min函数,今天用的#define宏定义的,比赛是写的函数。然后就抱着试试看的心态一改,。。。竟然过了。。。
注意给的数很大,int会溢出。
详情请见代码:
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 100005;
typedef long long ll;
//#define Min(a,b) (a)>(b)?(b):(a)
struct node
{
ll min,lazy;
}tree[N<<2];
int n,m;
ll Min(ll a,ll b)
{
return a > b?b:a;
}
void build(int num,int s,int e)
{
tree[num].min = 0;
tree[num].lazy = 0;
if(s == e)
return;
int mid = (s + e)>>1;
build(num<<1,s,mid);
build(num<<1|1,mid + 1,e);
}
ll nextint()
{
ll ret;
char c;
bool sig = false;
while(isspace(c = getchar()))
;
if(c == '-')
{
sig = true;
c = getchar();
}
ret = c - '0';
while((c = getchar()) >= '0' && c <= '9')
ret = ret * 10 + c - '0';
return sig ? -ret:ret;
}
void add(int num,int s,int e,int l,int r,int val)
{
if(s == e)
{
tree[num].min += val;
return;
}
if(s == l && e == r)
{
tree[num].lazy += val;
return;
}
if(tree[num].lazy)
{
tree[num].min += tree[num].lazy;
tree[num<<1].lazy += tree[num].lazy;
tree[num<<1|1].lazy += tree[num].lazy;
tree[num].lazy = 0;
}
int mid = (s + e)>>1;
if(r <= mid)
add(num<<1,s,mid,l,r,val);
else
{
if(l > mid)
add(num<<1|1,mid + 1,e,l,r,val);
else
{
add(num<<1,s,mid,l,mid,val);
add(num<<1|1,mid + 1,e,mid + 1,r,val);
}
}
tree[num].min = Min(tree[num<<1].min + tree[num<<1].lazy,tree[num<<1|1].min + tree[num<<1|1].lazy);
}
ll query(int num,int s,int e,int l,int r)
{
if(s == e)
return tree[num].min + tree[num].lazy;
if(s == l && e == r)
return tree[num].lazy + tree[num].min;
int mid = (s + e)>>1;
if(tree[num].lazy)
{
tree[num].min += tree[num].lazy;
tree[num<<1].lazy += tree[num].lazy;
tree[num<<1|1].lazy += tree[num].lazy;
tree[num].lazy = 0;
}
if(r <= mid)
return query(num<<1,s,mid,l,r);
else
{
if(l > mid)
return query(num<<1|1,mid + 1,e,l,r);
else
return Min(query(num<<1,s,mid,l,mid),query(num<<1|1,mid + 1,e,mid + 1,r));
}
}
void print(int num,int s,int e)
{
if(s == e)
{
printf("%lld %lld\n",tree[num].min,tree[num].lazy);
return;
}
int mid = (s + e)>>1;
print(num<<1,s,mid);
print(num<<1|1,mid + 1,e);
}
int main()
{
ll i,l,r,w,op;
while(~scanf("%lld%lld",&n,&m))
{
//build(1,1,n);
memset(tree,0,sizeof(tree));
for(i = 1;i <= n;i ++)
{
//scanf("%lld",&w);
w = nextint();
add(1,1,n,i,i,w);
}
while(m --)
{
//scanf("%lld%lld",&l,&r);
// char cc = getchar();
l = nextint();
r = getchar() - '0';
char cc;
while((cc = getchar()) >= '0' && cc <= '9')
r = r * 10 + cc - '0';
l ++;r ++;
if(cc == ' ')
{
//scanf("%lld",&w);
bool sig = false;
cc = getchar();
if(cc == '-')
{
sig = true;
cc = getchar();
}
w = cc - '0';
while((cc = getchar()) >= '0' && cc <= '9')
w = w * 10 + cc - '0';
if(sig)
w = -w;
// printf("w%lld\n",w);
if(l > r)
{
add(1,1,n,1,r,w);
add(1,1,n,l,n,w);
}
else
add(1,1,n,l,r,w);
}
else
{
if(l > r)
printf("%lld\n",Min(query(1,1,n,1,r),query(1,1,n,l,n)));
else
printf("%lld\n",query(1,1,n,l,r));
}
}
}
return 0;
}
/*
3 5
1 2 4
0 2
0 0 1
0 2
2 0 -2
2 0
7 10
1 2 3 4 5 6 7
0 3
4 1 -3
0 6
0 2 4
*/