一大清早起来 A 掉一道划分树+树状数组+离散化的题+近200行代码的题,勉强算是弥补了今晚不能做 CF 的遗憾了吧,该死的,怎么会这个时候交我回家呢?!!
题很裸,一看就知道是划分树求区间第 k 值 + 树状数组
给出题目连接,懒得写 html 了:http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=393&page=show_problem&problem=3035
注意不要上 hdu 上看题,上面样例给出的数据不全,但是可以在上面测题
具体怎么做的懒得讲了,直接上代码。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <string> #include <queue> #include <ctime> #include <cstdlib> #include <stack> #include <map> #include <set> #include <list> #define INT_INF 0x3fffffff #define LL_INF 0x3fffffffffffffff #define EPS 1e-12 #define MOD 1000000007 #define PI 3.14159265358979323846 #define N 100010 #define E 100010 using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef unsigned int Uint; typedef double DB; struct data { int st,en; } T[4*N]; int sorted[N]; int val[40][N]; int to_L[40][N]; int sum[N]; struct node { char name[20]; int st,en,k; } op[2*N]; vector<int>y; map<int,int> ihash; map<int,int> back; void make_disc() { sort(y.begin(),y.end()); y.erase(unique(y.begin(),y.end()),y.end()); for(int i=0; i<(int)y.size(); i++) { ihash[y[i]]=i+1; back[i+1]=y[i]; } } int get_sum(int *a,int pos) { int temp=0; while(pos>0) { temp+=a[pos]; pos-=pos&(-pos); } return temp; } int get_k(int *a,int k,int L,int R) { while(L<R) { int mid=(L+R)>>1; if(get_sum(a,mid)>=k) R=mid; else L=mid+1; } return L; } void update(int *a,int pos,int k) { while(pos<N) { a[pos]+=k; pos+=pos&(-pos); } } void build(int v,int st,int en,int deep) { T[v].st=st; T[v].en=en; if(st==en) return; int mid=(st+en)>>1; int mid_num=sorted[mid]; int same=mid-st+1; for(int i=st; i<=en; i++) if(val[deep][i]<mid_num) same--; int L=st , R=mid+1; for(int i=st; i<=en; i++) { if(i==st) to_L[deep][i]=0; else to_L[deep][i]=to_L[deep][i-1]; if(val[deep][i]<mid_num || val[deep][i]==mid_num && same>0) { val[deep+1][L++]=val[deep][i]; to_L[deep][i]++; if(val[deep][i]==mid_num) same--; } else val[deep+1][R++]=val[deep][i]; } build(v<<1,st,mid,deep+1); build(v<<1|1,mid+1,en,deep+1); } int query(int v,int st,int en,int k,int deep) { if(st==en) return val[deep][st]; int s1 , s2 , b1 , b2; if(st==T[v].st) s1=0; else s1=to_L[deep][st-1]; s2=to_L[deep][en]-s1; b1=(st-1-T[v].st+1)-s1; b2=(en-st+1)-s2; int mid=(T[v].st+T[v].en)>>1; if(k<=s2) return query(v<<1,T[v].st+s1,T[v].st+s1+s2-1,k,deep+1); else return query(v<<1|1,mid+1+b1,mid+1+b1+b2-1,k-s2,deep+1); } int main() { int n,ca=0; while(scanf("%d",&n)!=EOF) { y.clear(); back.clear(); ihash.clear(); int tot=0; for(int i=1; i<=n; i++) { scanf("%s",op[i].name); if(strcmp(op[i].name,"Insert")==0) { tot++; scanf("%d",&val[0][tot]); sorted[tot]=val[0][tot]; op[i].k=sorted[tot]; y.push_back(val[0][tot]); } if(strcmp(op[i].name,"Query_1")==0) scanf("%d%d%d",&op[i].st,&op[i].en,&op[i].k); if(strcmp(op[i].name,"Query_2")==0) { scanf("%d",&op[i].k); y.push_back(op[i].k); } if(strcmp(op[i].name,"Query_3")==0) scanf("%d",&op[i].k); } make_disc(); for(int i=1; i<=tot; i++) { int tmp=val[0][i]; val[0][i]=sorted[i]=ihash[tmp]; } sort(sorted+1,sorted+1+tot); build(1,1,tot,0); memset(sum,0,sizeof(sum)); LL ans1=0 , ans2=0 , ans3=0; for(int i=1; i<=n; i++) { if(strcmp(op[i].name,"Insert")==0) update(sum,ihash[op[i].k],1); if(strcmp(op[i].name,"Query_1")==0) ans1+=(LL)back[query(1,op[i].st,op[i].en,op[i].k,0)]; if(strcmp(op[i].name,"Query_2")==0) ans2+=(LL)get_sum(sum,ihash[op[i].k]); if(strcmp(op[i].name,"Query_3")==0) ans3+=(LL)back[get_k(sum,op[i].k,1,N-1)]; } printf("Case %d:\n",++ca); printf("%I64d\n%I64d\n%I64d\n",ans1,ans2,ans3); } return 0; }