「codecomb2098」stone
Description
n个石堆围成一圈,提供两种操作:
1、每次将[L,R]堆的石子数量+k,其中,1<=L,R<=n,k>=0。
2、询问有最多石子的那一堆有多少石子。
现在,要求在线解决该问题。
Input
第一行两个整数n和m,n表示石子圈的长度,m表示操作数量。
以下m行,首先一个是整数t,t=1或2,表示是哪种操作。 如果t=1,则后面跟三个整数l,r,k,表示区间[l,r]的所有石子堆石子数量+k,如果t=2表示上述询问操作。
Output
对于每一个询问,输出石子数量。
Sample Input
3 3
1 1 2 1
1 3 1 2
2
Sample Output
3
Hint
数据范围:
10%的数据m<=1000
40%的数据n<=100000
100%的数据n<2^32,m<=100000
答案保证在longint范围内
题解
用动态开点的线段树就水过了嘛。。标记永久化会比较不虚
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #define inf 2147483647 #define ll long long using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,root,sz; int ls[5000005],rs[5000005],mx[5000005],tag[5000005]; void add(int &k,int l,int r,int x,int y,int val) { if(!k)k=++sz; if(l==x&&y==r) { tag[k]+=val;mx[k]+=val; return; } int mid=(l+r)>>1; if(mid>=y)add(ls[k],l,mid,x,y,val); else if(mid<x)add(rs[k],mid+1,r,x,y,val); else { add(ls[k],l,mid,x,mid,val); add(rs[k],mid+1,r,mid+1,y,val); } mx[k]=max(mx[ls[k]],mx[rs[k]])+tag[k]; } int main() { n=read();m=read(); for(int i=1;i<=m;i++) { int t=read(); if(t==1) { int l=read(),r=read(),K=read(); if(l<=r)add(root,1,n,l,r,K); else add(root,1,n,l,n,K),add(root,1,n,1,r,K); } else printf("%d\n",mx[root]); } return 0; } |
Subscribe