玲珑杯Round #14 B题 RE:从零开始的异世界生活(离线+线段树)
2017-05-15 23:31
405 查看
题意:www.ifrog.cc/acm/problem/1117
分析:题解中给出了三种方法,但都需要一些我不会的数据结构,我给出我的方法——离线+线段树。你要问我怎么想到用线段树的?那我很抱歉地告诉你,我也不知道,就是赛后灵光一闪。对!没错!是赛后!为什么不是比赛的时候啊!!!
查询先不看,先看修改。操作一是插入一个数,没什么特别的;操作二是把所有小于x的数变成x,那么我这时就想到了要建立一个类似标签的数据结构,标签表示的是这个数,后面带上这个数的个数值。但是回头一想,不好办啊,一是写起来麻烦,第二个是每次操作就要扫一遍所有标签,复杂度是不是有点大啊;操作三是把所有大于x的数变成x,和操作二没有本质区别。那么还是要考虑复杂度,我想到了离线+线段树的做法。
每个x都有可能很大,不可能为1000000000建立线段树,那么很显然的就是想到了离散化。这里需要离散化的是操作一、二、三、五的数,自己想为什么。(后面的都是离散化之后的数据,请自己二分确定index)成功离散化之后,就建立线段树,一开始每一个x都是0个。对于操作一,那么就是先查询这个x已经有多少个了,然后加一之后重新更新x这个序号在集合中的个数;对于操作二,先查询小于等于x的数有多少个,然后将所有小于等于x的数都置为0个,然后单独置x的个数为前面小于等于x的数的个数;对于操作三,请参考操作二;对于操作四,用二分的方法查询0~m之间的个数,逐个比对,二分答案应该会把;对于操作五,那就更加简单了,直接查询小于等于x的数的个数减去等于x的个数。你会觉得我的写法有点奇怪,我是为了方便,这样写只要写一个线段树的update,中间还不加一些奇奇怪怪的判断,比如当前是不是第一个或者最后一个之类的。(当然,你也可以不这样写)
代码:仅供参考
#include <map> #include <set> #include <ctime> #include <stack> #include <cmath> #include <queue> #include <bitset> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <fstream> #include <cstdlib> #include <sstream> #include <cstring> #include <iostream> #include <algorithm> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define maxn 100000+10 #define maxm 10000+10 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define clr(x,y) memset(x,y,sizeof(x)) #define pii pair<int,int> #define mp make_pair #define FI first #define SE second #define IT iterator #define PB push_back #define Times 10 typedef long long ll; typedef unsigned long long ull; typedef long double ld; const double eps = 1e-14; //const double pi = acos(-1.0); const ll mod = 1e9+7; const int inf = 0x3f3f3f3f; const ll INF = (ll)1e18+300; const double delta = 0.98; inline void RI(int& x) { x=0; char c=getchar(); while(!((c>='0'&&c<='9')||c=='-'))c=getchar(); bool flag=1; if(c=='-') { flag=0; } while(c<='9'&&c>='0') { x=x*10+c-'0'; c=getchar(); } if(!flag)x=-x; } /*--------------------------------------------------*/ int dat[2][maxn]; int num[maxn]; int sum[maxn<<2]; int col[maxn<<2]; void build(int l,int r,int rt){ col[rt]=-1; sum[rt]=0; if(l==r){ return ; } int m=(l+r)>>1; build(lson); build(rson); } int erfen(int l,int r,int k){ while(l<=r){ int m=(l+r)>>1; if(num[m]==k)return m; else if(num[m]<k)l=m+1; else r=m-1; } } void pushup(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void pushdown(int rt,int len){ if(col[rt]!=-1){ sum[rt<<1]=(len-(len>>1))*col[rt]; sum[rt<<1|1]=(len>>1)*col[rt]; col[rt<<1]=col[rt]; col[rt<<1|1]=col[rt]; col[rt]=-1; } } int query(int l,int r,int rt,int L,int R){ if(L<=l&&r<=R){ return sum[rt]; } pushdown(rt,r-l+1); int m=(l+r)>>1; int ans=0; if(L<=m)ans+=query(lson,L,R); if(R>m) ans+=query(rson,L,R); pushup(rt); return ans; } void update(int l,int r,int rt,int L,int R,int p){ if(L<=l&&r<=R){ sum[rt]=(r-l+1)*p; col[rt]=p; return ; } pushdown(rt,r-l+1); int m=(l+r)>>1; if(L<=m)update(lson,L,R,p); if(R>m) update(rson,L,R,p); pushup(rt); } int main(){ //freopen("D:\\acm\\C-small-attempt0.in","r",stdin); //freopen("D:\\acm\\out.txt","w",stdout); int n; scanf("%d",&n); int len=0; for(int i=0;i<n;i++){ scanf("%d %d",&dat[0][i],&dat[1][i]); if(dat[0][i]<=3||dat[0][i]==5) num[len++]=dat[1][i]; } sort(num,num+len); len=unique(num,num+len)-num; build(0,len-1,1); for(int i=0;i<n;i++){ int op=dat[0][i]; int k=erfen(0,len-1,dat[1][i]); if(op==1){ int ss=query(0,len-1,1,k,k); update(0,len-1,1,k,k,ss+1); } else if(op==2){ int ss=query(0,len-1,1,0,k); update(0,len-1,1,0,k,0); update(0,len-1,1,k,k,ss); } else if(op==3){ int ss=query(0,len-1,1,k,len-1); update(0,len-1,1,k,len-1,0); update(0,len-1,1,k,k,ss); } else if(op==4){ int l=0,r=len-1; while(l<=r){ int m=(l+r)>>1; if(query(0,len-1,1,0,m)>=dat[1][i])r=m-1; else l=m+1; } printf("%d\n",num[l]); } else { printf("%d\n",query(0,len-1,1,0,k)-query(0,len-1,1,k,k)); } } return 0; }
其实我已经退役很久了,这个博客也不怎么用了。但是偶尔还是会更新一些题目或者比赛,有兴趣的朋友可以关注一下,或者关注一下我的新博客shengtao96。
相关文章推荐
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- 玲珑杯 1117 - RE:从零开始的异世界生活(线段树)
- HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)
- SPOJ GSS2 离线线段树
- 线段树离线处理(区间内出现k次的数有多少个)Codeforces Round #136 (Div. 2)
- HDU 6162 Ch’s gift (树剖 + 离线线段树)
- ZOJ3633 Alice's present 线段树离线 || 主席树在线