2015 UESTC 数据结构专题A题 秋实大哥与小朋友 线段树 区间更新,单点查询,离散化
秋实大哥与小朋友
Time Limit: 1 Sec Memory Limit: 256 MB
题目连接
http://acm.uestc.edu.cn/#/contest/show/59Description
秋实大哥以周济天下,锄强扶弱为己任,他常对天长叹:安得广厦千万间,大庇天下寒士俱欢颜。
所以今天他又在给一群小朋友发糖吃。
他让所有的小朋友排成一行,从左到右标号。在接下去的时间中,他有时会给一段区间的小朋友每人v颗糖,有时会问第x个小朋友手里有几颗糖。
这对于没上过学的孩子来说实在太困难了,所以你看不下去了,请你帮助小朋友回答所有的询问。
Input
第一行包含两个整数n,m,表示小朋友的个数,以及接下来你要处理的操作数。
接下来的m行,每一行表示下面两种操作之一:
0 l r v : 表示秋实大哥给[l,r]这个区间内的小朋友每人v颗糖
1 x : 表示秋实大哥想知道第x个小朋友手里现在有几颗糖
1≤m,v≤100000,1≤l≤r≤n,1≤x≤n,1≤n≤100000000。1≤x≤n,1≤n≤100000000。
接下来的m行,每一行表示下面两种操作之一:
0 l r v : 表示秋实大哥给[l,r]这个区间内的小朋友每人v颗糖
1 x : 表示秋实大哥想知道第x个小朋友手里现在有几颗糖
1≤m,v≤100000,1≤l≤r≤n,1≤x≤n,1≤n≤100000000。1≤x≤n,1≤n≤100000000。
Output
对于每一个1 x操作,输出一个整数,表示第x个小朋友手里现在的糖果数目。
Sample Input
3 4
0 1 3 1
1 2
0 2 3 3
1 3
0 1 3 1
1 2
0 2 3 3
1 3
Sample Output
1
4
4
HINT
题意
题解:
灰常简单的一个区间更新+单点查询问题,但是n比较大!比较大!肿么办?这位 小彭玉请告诉我,肿么办?
哈,我们先把数读进来,然后排个序,维护个前缀和,或者来个map,就可以离散化啦!
我真是机智呀!
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=100000*5; typedef long long LL; struct node { int lft,rht; LL sum,add; int mid(){return MID(lft,rht);} void fun(LL tmp) { add+=tmp; sum+=(rht-lft+1)*tmp; } }; int y[N]; struct Segtree { node tree[N*4]; void relax(int ind) { if(tree[ind].add) { tree[LL(ind)].fun(tree[ind].add); tree[RR(ind)].fun(tree[ind].add); tree[ind].add=0; } } void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].sum=0; tree[ind].add=0; if(lft==rht) tree[ind].sum=y[lft]; else { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum; } } void updata(int st,int ed,int ind,int add) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) tree[ind].fun(add); else { relax(ind); int mid=tree[ind].mid(); if(st<=mid) updata(st,ed,LL(ind),add); if(ed> mid) updata(st,ed,RR(ind),add); tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum; } } LL query(int st,int ed,int ind) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) return tree[ind].sum; else { relax(ind); int mid=tree[ind].mid(); LL sum1=0,sum2=0; if(st<=mid) sum1=query(st,ed,LL(ind)); if(ed> mid) sum2=query(st,ed,RR(ind)); return sum1+sum2; } } }seg; int kiss[100000*5]; int dow[100000*5]; struct oi { int x,y,c,id,ty; }; oi ans[100000*5]; int tot1,tot2=1; int getid(int x) { int l=1,r=tot2; int mid=(l+r)>>1; while(dow[mid]!=x&&dow[l]!=x&&dow[r]!=x) { mid=(l+r)>>1; if(dow[mid]>x) r=mid; else l=mid+1; } if(dow[mid]==x) return mid; if(dow[l]==x) return l; if(dow[r]==x) return r; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { char str[5]; int a,b,c; memset(y,0,sizeof(y)); seg.build(1,100000*3,1); for(int i=0;i<m;i++) { scanf("%s",str); if(str[0]=='1') { scanf("%d",&a); ans[i].x=a,ans[i].y=a,ans[i].c=1,ans[i].id=i,ans[i].ty=-1; kiss[tot1++]=a; } else { scanf("%d%d%d",&a,&b,&c); ans[i].x=a,ans[i].y=b,ans[i].c=c,ans[i].id=i,ans[i].ty=1; kiss[tot1++]=a; kiss[tot1++]=b; } } tot2=0; sort(kiss,kiss+tot1); for(int i=0;i<tot1;i++) if(dow[tot2]!=kiss[i]) dow[++tot2]=kiss[i]; for(int i=0;i<m;i++) { if(ans[i].ty==-1) { int x=getid(ans[i].x); printf("%lld\n",seg.query(x,x,1)); } else { int x=getid(ans[i].x),y=getid(ans[i].y),z=ans[i].c; seg.updata(x,y,1,z); } } } return 0; }