2015多校联赛第一场

对于弱渣,表示只过了两题。。。还都是水题。。。

1001.

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288

题意:给定一个整数n,然后l的取值是1~n,r的取值是i~n,求每个i,j范围内有多少个a[i]满足,除自己以外没有其它因子。

题解:如果从区间暴力,n^4,绝笔超时。然后发现a[i]的范围只有10000,那么通过查找每个数字的[l,r],算出能够满足多少个空间,把所有满足的数值加起来即可,不过如果都扫一遍,n^2还是超时。(楼主就这样T了一发),之后通过标记因子出现与否,维护因子极值即可。前后各扫一次。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 const int maxn = 100000+50;
  8 const int mmm = 1000000007;
  9 struct st{
 10     int posmi;
 11     int posmx;
 12     int temp;    
 13 };
 14 st b[20000];
 15 struct ss{
 16     int l;
 17     int r;
 18     int x;
 19 };
 20 ss a[maxn];
 21 int main()
 22 {
 23     int n;
 24 //    freopen("1001.in","r",stdin);
 25 //    freopen("20.txt","w",stdout);
 26     while(~scanf("%d",&n))
 27     {
 28       memset(b,0,sizeof(b));
 29       memset(a,0,sizeof(a));
 30       for(int i=0;i<n;i++)
 31           scanf("%d",&a[i].x);
 32         for(int i=0;i<n;i++)
 33       {
 34           a[i].l=0;
 35           a[i].r=n-1;
 36           int tt=sqrt(a[i].x);
 37           for(int j=1;j<=tt;j++)
 38         {
 39             if(a[i].x%j==0&&b[j].temp)
 40             {
 41                 if(a[i].x!=j)
 42                 {
 43                 if(a[i].l==0)
 44                     a[i].l=b[j].posmx+1;
 45                 else
 46                     a[i].l=max(a[i].l,b[j].posmx+1);
 47                 }
 48             }
 49             if(a[i].x%j==0&&b[a[i].x/j].temp)
 50             {
 51                 int kk=a[i].x/j;
 52                 if(kk!=a[i].x)
 53                 {
 54                 if(a[i].l==0)
 55                     a[i].l=b[kk].posmx+1;
 56                 else
 57                     a[i].l=max(a[i].l,b[kk].posmx+1);
 58                 }
 59             }
 60             
 61         }
 62         if(b[a[i].x].temp)
 63         {
 64                 if(a[i].l==0)
 65                     a[i].l=b[a[i].x].posmx+1;
 66                 else
 67                     a[i].l=max(a[i].l,b[a[i].x].posmx+1);
 68         }
 69         if(b[a[i].x].posmx==0)
 70           b[a[i].x].posmx = i;
 71           else 
 72           b[a[i].x].posmx=max(b[a[i].x].posmx,i);
 73         b[a[i].x].temp=1;
 74       }
 75       memset(b,0,sizeof(b));
 76       for(int i=n-1;i>=0;i--)
 77       {
 78           int tt=sqrt(a[i].x);
 79           for(int j=1;j<=tt+1;j++)
 80         {
 81             if(a[i].x%j==0&&b[j].temp)
 82             {
 83                 if(a[i].x!=j)
 84                 {
 85                 if(a[i].r==n-1)
 86                     a[i].r=b[j].posmi-1;
 87                 else
 88                     a[i].r=min(a[i].r,b[j].posmi-1);
 89                 }
 90             }
 91             if(a[i].x%j==0&&b[a[i].x/j].temp)
 92             {    int kk=a[i].x/j;
 93                 if(kk!=a[i].x)
 94                 {
 95                 if(a[i].r==n-1)
 96                     a[i].r=b[kk].posmi-1;
 97                 else
 98                     a[i].r=min(a[i].r,b[kk].posmi-1);
 99                 }
100             }
101         }
102         if(b[a[i].x].temp)
103         {
104                 if(a[i].r==n-1)
105                     a[i].r=b[a[i].x].posmi-1;
106                 else
107                     a[i].r=min(a[i].r,b[a[i].x].posmi-1);
108         }
109         if(b[a[i].x].posmi==0)
110               b[a[i].x].posmi = i;
111           else
112               b[a[i].x].posmi=min(b[a[i].x].posmi,i);
113         b[a[i].x].temp=1;
114       }
115        long long int sum=0,k1,k2;
116       for(int i=0;i<n;i++)
117       {
118      //    cout<<a[i].l<<" "<<a[i].r<<endl;
119         k1=a[i].r-i+1,k2=i-a[i].l+1;
120           sum=(sum+k1*k2)%mmm;
121       }
122       printf("%I64d\n",sum);
123     }
124    return 0;
125 }
View Code

1002.

题意:给定一个n,k,输入n个数,求有多少个区间,满足:该区间内所有数,是否任意两个的差值都小于k。

题解:RMQ+二分。

线段树来做的话,查询时会变成O(n*logn*logn),会超时 = =。所以只能用查询效率为O(1)的RMQ。

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn = 100000+50;
 7 int maxsum[maxn][20];
 8 int minsum[maxn][20];
 9 int a[maxn];
10 void RMQ(int num) //预处理->O(nlogn)
11 {
12         for(int i=0;i<num;i++)
13                 maxsum[i][0]=minsum[i][0]=a[i];
14     for(int j =1; j < 20; ++j)
15         for(int i = 0; i < num; ++i)
16             if(i + (1 << j) - 1 <= num)
17             {
18                 maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]);
19                 minsum[i][j] = min(minsum[i][j - 1], minsum[i + (1 << (j - 1))][j - 1]);
20             }
21 }
22 
23 int query(int l,int r)
24 {
25         int k=0;
26         while((1<<(k+1))<(r-l+1))
27                 k++;
28         int tt=min(minsum[l][k],minsum[r-(1<<k)+1][k]);
29         int t=max(maxsum[l][k],maxsum[r-(1<<k)+1][k]);
30         return t-tt;
31 }
32 
33 int main()
34 {
35     int test;
36     //freopen("1002.in","r",stdin);
37     //freopen("out.txt","w",stdout);
38     cin>>test;
39     int m,k;
40     while(test--)
41     {
42         scanf("%d%d",&m,&k);
43         for(int i=0;i<m;i++)
44                 scanf("%d",&a[i]);
45         RMQ(m);
46         int x;
47         long long int sum=0;
48         for(int i=0;i<m;i++)
49         {
50                 int l=i,r=m-1;
51                 int mid;
52                 while(l+1<r)
53                 {
54                         mid=(l+r)>>1;
55                         if(query(i,mid)<k)
56                                 l=mid;
57                         else
58                                 r=mid;
59                 }
60                 if(query(i,r)<k)
61                 sum+=r-i+1;
62                 else
63                         sum+=l-i+1;
64         }
65         printf("%I64d\n",sum);
66     }
67     return 0;
68 }
View Code

 

posted on 2015-07-22 13:47  小松song  阅读(141)  评论(0)    收藏  举报

导航