NOIP2011 [提高组] 选择客栈

前言

今天考了NOIP11年的一些题,这道题是Day2 T1,考试的时候我只想出了O(n^2)的算法,拿了七十分,下午改了两个多小时,但是还是只写了一个O(nlogn+k)的算法,但是在机房的老爷机上已经可以过了

题目描述

链接在这里 : https://www.luogu.org/problem/P1311

思路

70分

我们可以把每一种主题相同的客栈先用二维数组存下来,同时记录满足费用 <=p 的客栈,再用O(n^2)扫描区间累加

70 pts CODE

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N=200002;
 7 const int M=52;
 8 int n,k,p;
 9 struct data{
10     int color;
11     int xf;
12 }jd[N];
13 int f[M][N],num[M];
14 int z[N],top=0;
15 bool vis[N];
16 long long ans=0;
17 bool check(int l,int r)
18 {
19     for (int i=l;i<=r;i++)
20     if (vis[i]) return true;
21     return false;
22 }
23 void cl()
24 {
25     for (int i=0;i<k;i++)
26     {
27         top=0;
28         for (int j=1;j<=num[i];j++)
29         z[++top]=f[i][j];
30         sort(z+1,z+top+1);
31         for (int j=1;j<=top;j++)
32         for (int t=j+1;t<=top;t++)
33         if (check(z[j],z[t])) ++ans;
34     }
35 }
36 int main()
37 {
38     //freopen("hotel.in","r",stdin);
39     //freopen("hotel.out","w",stdout);
40     scanf("%d %d %d",&n,&k,&p);
41     for (int i=1;i<=n;i++)
42     {
43         scanf("%d %d",&jd[i].color,&jd[i].xf);
44         if (jd[i].xf<=p) vis[i]=true;
45         f[jd[i].color][++num[jd[i].color]]=i;
46     }
47     cl();
48     printf("%lld",ans);
49     return 0;
50 }

正解(AC)

下来的时候,同机房A掉这道题的苣佬写了ST表,搞得我也写了一个来判断区间之间是否存在满足条件的咖啡店

复杂度 O(nlogn+k) ST表+查询

100 pts CODE

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N=200010;
 7 const int M=52;
 8 int n,k,p;
 9 struct data{
10     int color;
11     int xf;
12 }jd[N];
13 int f[M][N],num[M];
14 int z[N],top=0;
15 int mx[N][18],lg[N];
16 int vis[N];
17 long long ans=0;
18 inline int read()
19 {
20     char ch=getchar();
21     int x=0;bool flag=false;
22     while (!isdigit(ch)) flag^=!(ch^45),ch=getchar();
23     while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
24     if (flag) x=-x;return x;
25 }
26 inline void st()
27 {
28     lg[0]=-1;
29     for (int i=1;i<=n;i++) lg[i]=(i&i-1)?lg[i-1]:(lg[i-1]+1);
30     for (int i=1;i<=n;i++) mx[i][0]=vis[i];
31     for (int j=1;j<=lg[n];j++)
32       for (int i=1;i<=n-(1<<j)+1;i++)
33       mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
34 }
35 inline int rmq(int l,int r)
36 {
37     int k=lg[r-l+1];
38     return max(mx[l][k],mx[r-(1<<k)+1][k]);
39 }
40 inline void cl()
41 {
42     
43     for (int i=0;i<k;i++)
44     {
45         top=0;
46         for (int j=1;j<=num[i];j++)
47         z[++top]=f[i][j];
48         if (top==1) continue;
49         int head=1,tail=2;
50         while (1)
51         {
52             if (rmq(z[head],z[tail])==1)
53             {
54                 ans+=top-tail+1;
55                 ++head;
56                 tail=head+1;
57             }
58             else ++tail;
59             if (head==top||head==top+1) break;
60             if (tail==top+1)
61             {
62                 ++head;
63                 tail=head+1;
64             }
65         }
66     }
67 }
68 int main()
69 {
70     //freopen("hotel.in","r",stdin);
71     //freopen("hotel.out","w",stdout);
72     n=read(),k=read(),p=read();
73     for (int i=1;i<=n;i++)
74     {
75         jd[i].color=read(),jd[i].xf=read();
76         if (jd[i].xf<=p) vis[i]=1;
77         f[jd[i].color][++num[jd[i].color]]=i;
78     }
79     st();
80     cl();
81     printf("%lld",ans);
82     return 0;
83 }

测评环境

机房测评机配置

 比CCF测评机配置低多了

猜你喜欢

转载自www.cnblogs.com/Snowindfly/p/11426190.html