题目描述
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范围内
离散完线段树维护区间最大值
我会说原来我一直不会线段树维护区间最大最小?
不过黄巨大说正解其实是类似可持久化线段树的搞法
一开始直接搞出l=1 r=2^32的第一条线段,然后修改时照样修改,遇到完全覆盖的时候直接更新tag退出,否则递归,没有左右节点的就插入一条边,这样每次最坏插入一条链,只有32个
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<deque> #include<set> #include<map> #include<ctime> #define LL long long #define inf 2147483647 #define pa pair<int,int> #define pi 3.1415926535897932384626433832795028841971 #define mod 100007 #define N 300010 using namespace std; struct hashing{ int next,rnk; LL v; }hash[N]; bool operator <(const hashing &a,const hashing &b){return a.v<b.v;} struct oprations{ int l,r,x; bool opr;//0:work 1:query }w[N]; int rnk[N]; int head[mod]; int n,m,cnt; LL chafen[N]; LL sum,ans,toadd; inline int ins(LL w) { LL u=w%mod; for (int i=head[u];i;i=hash[i].next) if (hash[i].v==w) return i; hash[++cnt].v=w; hash[cnt].next=head[u]; hash[cnt].rnk=cnt; head[u]=cnt; return cnt; } inline LL read() { LL 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; } struct segtree{ int l,r,mx,tag; }tree[1000010]; int treesize; inline void pushdown(int k) { int t=tree[k].tag; tree[k].tag=0; tree[k<<1].tag+=t; tree[k<<1|1].tag+=t; tree[k<<1].mx+=t; tree[k<<1|1].mx+=t; } inline void update(int k) { if (tree[k].l==tree[k].r)return; tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx); } inline void buildtree(int now,int l,int r) { tree[now].l=l;tree[now].r=r; if (l==r)return; int mid=(l+r)>>1; buildtree(now<<1,l,mid); buildtree(now<<1|1,mid+1,r); } inline void add(int now,int l,int r,int dat) { pushdown(now); int x=tree[now].l,y=tree[now].r; if (x==l&&y==r) { tree[now].tag+=dat; tree[now].mx+=dat; return; } int mid=(x+y)>>1; if (r<=mid)add(now<<1,l,r,dat); else if(l>mid)add(now<<1|1,l,r,dat); else { add(now<<1,l,mid,dat); add(now<<1|1,mid+1,r,dat); } update(now); } int main() { n=read();m=read(); for (int i=1;i<=m;i++) { w[i].opr=(read()==2); if (!w[i].opr) { w[i].l=ins(read()); w[i].r=ins(read()); w[i].x=read(); } } sort(hash+1,hash+cnt+1); for (int i=1;i<=cnt;i++) rnk[hash[i].rnk]=i; for (int i=1;i<=m;i++) if (!w[i].opr) { w[i].l=rnk[w[i].l]; w[i].r=rnk[w[i].r]; } buildtree(1,1,cnt); for (int i=1;i<=m;i++) { if(w[i].opr)printf("%d ",tree[1].mx); else { if (w[i].l>w[i].r) { add(1,1,w[i].r,w[i].x); add(1,w[i].l,cnt,w[i].x); }else add(1,w[i].l,w[i].r,w[i].x); } } }