【数据结构】cf91E. Igloo Skyscraper
http://codeforces.com/problemset/problem/91/E
很简单的题意,给出n条直线编号分别为1~n,再给去m个询问,要求出第L条~第R条直线,在x=xi时最高的是那一条。
作为一个弱菜我只想到了,O(n*n½ log(n½))的暴力方法,=。=,就是分块sqrt(n)个区域,将询问离线按x坐标递增,每个块内用堆维护求出当前x坐标下最高的直线编号。后来问了我队友,他告诉我用线段树可以处理,相当于线段树每个节点(li,ri),上维护一个下凸曲线,每个节点的曲线可以由其两个子结点线性合并出来,故每层复杂度是O(n) ,总复杂度O(n log(n) )。
今天太不在状态了,这两个100行左右的程序,墨迹了一个下午,第二个版本还没AC成功,=。=~。自己怎么对拍都没问题,于是决定不管之了
线段树版本
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #define maxn 100005 6 #define inf 0x7fffffff 7 using namespace std; 8 typedef long long LL; 9 10 int n,m; 11 struct Line{ 12 int a,b; 13 int id; 14 void init(int i){ scanf("%d%d", &a, &b ); id = i; } 15 bool operator<(Line c){ 16 return (a!=c.a)?(a<c.a):(b<c.b); 17 } 18 }data[maxn]; 19 bool cmp(Line a , Line b ,int t){ 20 return a.a+((LL)a.b*t) < b.a+((LL)b.b*t); 21 } 22 int overtake(Line a, Line b){ 23 int t = (b.a-a.a)/(a.b-b.b); 24 if ( cmp(a,b,t) ) t++; 25 return t; 26 } 27 struct Segtree{ 28 int left[maxn*4],right[maxn*4]; 29 int num[maxn*4]; 30 vector<Line> g[maxn*4]; 31 vector<int> h[maxn*4]; 32 void meger(int step){ 33 int l = step*2 , r = step*2+1,i = 0 , j = 0; 34 while ( i != num[l] || j != num[r] ){ 35 if ( i == num[l] ) g[step].push_back( g[r][j++] ); 36 else if ( j == num[r] ) g[step].push_back( g[l][i++] ); 37 else 38 if ( g[l][i].b < g[r][j].b || g[l][i].b==g[r][j].b&&g[l][i].a>g[r][j].a ) 39 g[step].push_back( g[l][i++] ); 40 else 41 g[step].push_back( g[r][j++] ); 42 } 43 int cnt = num[l]+num[r]; 44 while ( h[step].size()<num[l]+num[r] ) h[step].push_back(0); 45 h[step][0] = -inf; num[step] = 1; 46 for (int i = 1; i<cnt; i++){ 47 if ( g[step][i].b == g[step][num[step]-1].b ) continue; 48 int t = overtake( g[step][i] , g[step][num[step]-1] ); 49 while ( t <= h[step][num[step]-1] ) { 50 num[step]--; 51 t = overtake( g[step][i] , g[step][num[step]-1] ); 52 } 53 g[step][num[step]++] = g[step][i]; 54 h[step][num[step]-1] = overtake( g[step][num[step]-1] , g[step][num[step]-2] ); 55 } 56 } 57 void build(int l,int r,int step){ 58 left[step] = l , right[step] = r; 59 g[step].clear() , h[step].clear(); 60 if ( l == r ){ 61 g[step].push_back( data[l] ); 62 h[step].push_back(-inf); 63 num[step] = 1; 64 return; 65 } 66 int mid = (left[step]+right[step])>>1; 67 build( l , mid , step*2 ); 68 build(mid+1 ,r , step*2+1 ); 69 meger(step); 70 } 71 pair<LL,int> ask(int l,int r,int t,int step){ 72 if ( left[step] == l && right[step] == r ) { 73 int p = 0 , q = num[step]-1,k = 0; 74 while ( p<=q ){ 75 int mid = (p+q)>>1; 76 if ( h[step][mid] <= t ) k = mid , p = mid+1; 77 else q = mid-1; 78 } 79 return make_pair( g[step][k].a+((LL)g[step][k].b)*t , g[step][k].id ); 80 } 81 int mid = ( left[step]+right[step] )>>1; 82 if ( r<=mid ) return ask(l,r,t,step*2); 83 else if ( mid<l ) return ask(l,r,t,step*2+1); 84 else return max( ask(l,mid,t,step*2) , ask(mid+1,r,t,step*2+1) ); 85 } 86 }tree; 87 int main(){ 88 scanf("%d%d",&n, &m ); 89 for (int i = 1; i<=n; i++) data[i].init(i); 90 tree.build(1,n,1); 91 while ( m -- ){ 92 int l, r,t; 93 scanf("%d%d%d", &l , &r, &t ); 94 printf("%d\n" , tree.ask(l,r,t,1).second ); 95 } 96 return 0; 97 }
分块版本
1 //By Lin 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 #define inf 0x7fffffff 7 #define maxn 100050 8 #define sqr(x) ((x)*(x)) 9 using namespace std; 10 typedef long long LL; 11 12 int n,m; 13 struct Ask{ 14 int l,r,t,num; 15 void init(int i) { scanf("%d%d%d", &l , &r, &t ); l--,r--; num = i; } 16 }asks[maxn]; 17 int ans[maxn]; 18 bool cmp1( const Ask &a , const Ask &b) { return a.t < b.t; } 19 20 struct Line{ 21 int a,b; 22 }data[maxn]; 23 inline LL compute( Line a, int t ){ 24 return a.a+((LL)a.b)*t; 25 } 26 inline int overtake( Line a, Line b){ 27 if ( a.b == b.b && a.a > b.a ) return -inf; 28 if ( a.b <= b.b ) return inf; 29 int t = (b.a-a.a)/(a.b-b.b); 30 if ( compute(a,t) < compute(b,t) ) t++; 31 return t; 32 33 } 34 int kcnt,len; 35 struct Node{ 36 int t,w,to; 37 Node(int _t ,int _w , int _to):t(_t),w(_w),to(_to){} 38 bool friend operator<( const Node&a , const Node&b){ 39 return a.t > b.t; 40 } 41 }; 42 priority_queue<Node> stack[400]; 43 int mx[400]; 44 bool check(LL &x, LL y){ 45 if ( x < y ) { x = y; return true; } 46 return false; 47 } 48 int main(){ 49 scanf("%d%d", &n, &m ); 50 for (int i = 0; i<n; i++) scanf("%d%d", &data[i].a , &data[i].b ); 51 for (len = 0; sqr(len+1)<=n; len++); 52 kcnt = n/len+(n%len==0?0:1); 53 for (int k = 0; k<kcnt; k++){ 54 int st = k*len , ed = min(n,(k+1)*len); 55 mx[k] = st; 56 for (int i = st; i<ed; i++) 57 if ( data[i].b<data[mx[k]].b ) mx[k] = i; 58 // if ( k == 3 ) printf("%d %d\n" , data[mx[k]].a , data[mx[k]].b ); 59 for (int i = st; i<ed; i++) if ( i != mx[k] ) { 60 stack[k].push( Node(overtake(data[i],data[mx[k]]),i,mx[k]) ); 61 // if ( k == 3 ) printf("%d,%d_%d %d %d\n",data[i].a,data[i].b, overtake(data[i],data[mx[k]]),i,mx[k] ); 62 } 63 } 64 for (int i = 0; i<m; i++) asks[i].init(i); 65 sort( asks, asks+m, cmp1 ); 66 // printf("%d\n" , len ); 67 for (int o = 0; o<m; o++){ 68 int l = asks[o].l , r = asks[o].r, 69 st = l/len+1 , ed = r/len, t = asks[o].t; 70 if ( asks[o].num == 31120 ) printf("%d %d %d %d %d\n" , l , r , st , ed , t ); 71 LL key = -(1ll<<60) , id = 0; 72 if ( st > ed ) { 73 for (int i = l; i<=r; i++) if ( check(key,compute(data[i],t)) ) id = i; 74 }else{ 75 for (int i = l; i<st*len; i++) if ( check(key,compute(data[i],t)) ) id =i; 76 for (int i = ed*len; i<=r; i++)if ( check(key,compute(data[i],t)) ) id =i; 77 for (int k = st; k<ed; k++){ 78 while ( !stack[k].empty() && stack[k].top().t <= t ){ 79 int w = stack[k].top().w , to = stack[k].top().to; 80 stack[k].pop(); 81 // if ( k == 3 ) printf("!%d %d %d\n" , w, to , t ); 82 if ( to == mx[k] ) mx[k] = w; 83 else { 84 stack[k].push( Node(overtake(data[w],data[mx[k]]),w,mx[k]) ); 85 // printf("now %d %d %d\n" , overtake(data[w],data[mx[k]]),w,mx[k]); 86 } 87 } 88 // printf("%d %d\n" , k , mx[k] ); 89 if ( check(key,compute(data[mx[k]],t)) ) id = mx[k]; 90 } 91 } 92 ans[asks[o].num] = id; 93 } 94 for (int i = 0; i<m; i++) printf("%d\n" , ans[i]+1 ); 95 return 0; 96 }