题目链接:点击打开链接
题目大意:给出n个格子,三种操作,D k:消除第k个格子,R:恢复最后一次消除的格子,Q k:问和k相连的最长连续序列。
求最长连续序列,线段树统计每段中被消除的最大点和最小点,更新点k,查询段[1,k][k,n],然后相减得到结果
#include <cstdio> #include <cstring> #include <stack> #include <algorithm> using namespace std ; #define INF 0x3f3f3f3f int cl_max[500000] , cl_min[500000] ; stack <int> sta ; void push_up(int rt) { cl_max[rt] = max(cl_max[rt<<1],cl_max[rt<<1|1]) ; cl_min[rt] = min(cl_min[rt<<1],cl_min[rt<<1|1]) ; } void update(int k,int flag,int l,int r,int rt) { if(l == r) { if( flag == -1 ) cl_max[rt] = 0 , cl_min[rt] = INF ; else cl_max[rt] = cl_min[rt] = k ; return ; } if( k <= (l+r)/2 ) update(k,flag,l,(l+r)/2,rt<<1) ; else update(k,flag,(l+r)/2+1,r,rt<<1|1) ; push_up(rt) ; } int query1(int ll,int rr,int l,int r,int rt) { if( rr < l || ll > r ) return 0 ; if( ll <= l && rr >= r ) return cl_max[rt] ; return max(query1(ll,rr,l,(l+r)/2,rt<<1),query1(ll,rr,(l+r)/2+1,r,rt<<1|1)) ; } int query2(int ll,int rr,int l,int r,int rt) { if( rr < l || ll > r ) return INF ; if( ll <= l && rr >= r ) return cl_min[rt] ; return min(query2(ll,rr,l,(l+r)/2,rt<<1),query2(ll,rr,(l+r)/2+1,r,rt<<1|1)) ; } int main() { int n , m , k , min1 , max1 ; char s[5] ; while( scanf("%d %d", &n, &m) !=EOF ) { memset(cl_max,0,sizeof(cl_max)) ; memset(cl_min,INF,sizeof(cl_min)) ; while( !sta.empty() ) sta.pop() ; while( m-- ) { scanf("%s", s) ; if( s[0] == 'D' ) { scanf("%d", &k) ; sta.push(k) ; update(k,1,1,n,1) ; } else if( s[0] == 'Q' ) { scanf("%d", &k) ; max1 = query1(1,k,1,n,1) ; min1 = query2(k,n,1,n,1) ; //printf("Q--> max1 = %d min1 = %d\n", max1 , min1) ; if( min1 == INF ) min1 = n+1 ; if( max1 == min1 ) printf("0\n") ; else printf("%d\n", min1-1-max1 ) ; } else{ k = sta.top() ; sta.pop() ; update(k,-1,1,n,1) ; } } } return 0 ; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-08 14:48:11