[BZOJ4358]permu

题目大意:
  $P$为$1\sim n(n\leq50000)$的一个排列。给出$m(m\leq50000)$个询问,每次询问区间$[l,r]$中,最长值域连续段长度。

思路:
  莫队+线段树。线段树上维护区间最长值域连续段长度、与区间左端点相连的最长值域连续段长度和与区间右端点相连的最长值域连续段长度。时间复杂度$O(n\sqrt n\log n)$。
  然后就TLE了,看了题解才知道标算原来是$O(n\sqrt n)$的莫队+栈或者KD树,然而也看到不少线段树卡常A掉的,不过我怎么卡常都A不掉,好像是BZOJ更新后卡时更准了。最后在DBZOJ上交了一发,只跑了8000ms。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<sys/mman.h>
 4 #include<sys/stat.h>
 5 class BufferedInputStream {
 6     private:
 7         char *buf,*p;
 8         int size;
 9     public:
10         BufferedInputStream() {
11             register int fd=fileno(stdin);
12             struct stat sb;
13             fstat(fd,&sb);
14             size=sb.st_size;
15             p=buf=reinterpret_cast<char*>(mmap(0,size,PROT_READ,MAP_PRIVATE,fileno(stdin),0));
16         }
17         char getchar() {
18             return (p==buf+size||*p==EOF)?EOF:*p++;
19         }
20 };
21 BufferedInputStream in;
22 inline int getint() {
23     register char ch;
24     while(!__builtin_isdigit(ch=in.getchar()));
25     register int x=ch^'0';
26     while(__builtin_isdigit(ch=in.getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
27     return x;
28 }
29 const int N=50001,M=50000;
30 int p[N],ans[M],block,pos[N];
31 struct Query {
32     int l,r,id;
33     bool operator < (const Query &another) const {
34         return l/block<another.l/block||(l/block==another.l/block&&r<another.r);
35     }
36 };
37 Query q[M];
38 inline int max(const int &a,const int &b) {
39     return a>b?a:b;
40 }
41 class SegmentTree {
42     #define _par >>1
43     #define _left <<1
44     #define _right <<1|1
45     private:
46         int smax[N<<2],lmax[N<<2],rmax[N<<2],len[N<<2];
47         void push_up(const int &p) {
48             lmax[p]=lmax[p _left];
49             if(__builtin_expect(smax[p _left]==len[p _left],0)) lmax[p]=max(lmax[p],smax[p _left]+lmax[p _right]);
50             rmax[p]=rmax[p _right];
51             if(__builtin_expect(smax[p _right]==len[p _right],0)) rmax[p]=max(rmax[p],smax[p _right]+rmax[p _left]);
52             smax[p]=max(max(lmax[p],rmax[p]),max(max(smax[p _left],smax[p _right]),rmax[p _left]+lmax[p _right]));
53         }
54     public:
55         void build(const int &p,const int &b,const int &e) {
56             len[p]=e-b+1;
57             if(b==e) {
58                 pos[b]=p;
59                 return;
60             }
61             const int mid=(b+e)>>1;
62             build(p _left,b,mid);
63             build(p _right,mid+1,e);
64         }
65         void modify(const int &p) {
66             smax[p]=lmax[p]=rmax[p]=smax[p]^1;
67             for(register int q=p _par;q;q=q _par) push_up(q);
68         }
69     #undef _par
70     #undef _left
71     #undef _right
72 };
73 SegmentTree t;
74 int main() {
75     const int n=getint(),m=getint();
76     block=__builtin_sqrt(n);
77     t.build(1,1,n);
78     for(register int i=1;i<=n;i++) p[i]=getint();
79     for(register int i=0;i<m;i++) {
80         const int l=getint(),r=getint();
81         q[i]=(Query){l,r,i};
82     }
83     std::sort(&q[0],&q[m]);
84     for(register int i=0,l=1,r=0;i<m;i++) {
85         while(r<q[i].r) t.modify(pos[p[++r]]);
86         while(l>q[i].l) t.modify(pos[p[--l]]);
87         while(r>q[i].r) t.modify(pos[p[r--]]);
88         while(l<q[i].l) t.modify(pos[p[l++]]);
89         ans[q[i].id]=*((int*)&t+1);
90     }
91     for(register int i=0;i<m;i++) {
92         __builtin_printf("%d\n",ans[i]);
93     }
94     return 0;
95 }

 

posted @ 2018-03-23 10:33  skylee03  阅读(178)  评论(0编辑  收藏  举报