2015 Multi-University Training Contest 1

最近真是太废柴了,题没做几道,也没学什么新知识,多校做了三场也没总结~诶!好好学吧!

多校第一场感觉被完虐...orz...

 

Hdu 5288 OO’s Sequence

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

题意:

  f(l,r)表示ai%aj0i(i[l,r],j[l,r],ji)
  已知n个数 a1,a2,an,求

  

思路:aiaiaj,ai%aj0ajai
ai,L[i],R[i],ans+=(i-L[i])*(R[i]-i);

参考代码:

  

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 const int N=100000;
 5 #define Mod 1000000007
 6 using namespace std;
 7 int a[N+10],id[N+10],L[N+10],R[N+10];
 8 int main()
 9 {
10     int n;
11     while(scanf("%d",&n)!=EOF)
12     {
13         for(int i=1; i<=n; i++)
14             scanf("%d",&a[i]);
15         memset(id,0,sizeof(id));
16         for(int i=1; i<=n; i++)   //向左找最近的因子下标
17         {
18             L[i]=0;
19             for(int j=1; j*j<=a[i]; j++)
20                 if(a[i]%j==0)    //j和a[i]/j都为a[i]的因子
21                 {
22                     if(id[j])
23                         L[i]=max(L[i],id[j]);  //取最大的下标即为最近的
24                     if(id[a[i]/j])
25                         L[i]=max(L[i],id[a[i]/j]);
26                 }
27             id[a[i]]=i;  //记录a[i]的下标
28         }
29         memset(id,0,sizeof(id));
30         for(int i=n; i>=1; i--)   //向右找最近的因子下标
31         {
32             R[i]=n+1;
33             for(int j=1; j*j<=a[i]; j++)
34                 if(a[i]%j==0)
35                 {
36                     if(id[j])
37                         R[i]=min(R[i],id[j]);
38                     if(id[a[i]/j])
39                         R[i]=min(R[i],id[a[i]/j]);
40                 }
41             id[a[i]]=i;
42         }
43         long long ans=0;
44         for(int i=1; i<=n; i++)
45             ans=(ans+(long long)(i-L[i])*(R[i]-i)%Mod)%Mod;
46         printf("%I64d\n",ans);
47     }
48     return 0;
49 }
View Code

 

 

Assignment

 

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

题意:  求有多少个区间满足区间内任意两个数的差值小于k

 

思路:  区间内最大差值为区间内最大值与最小值的差,只要其差满足条件,

   则该区间符合条件左区间l先固定,去找最大区间符合条件,即[l,r-1]符合,

   那么ans+=((rl)/2)+rl,然后r不变,l不断加1,直到找到符合条件的 [l,r]为止,

   那么[l,j-1]会被重复算,需要减掉.

   为了更快的查询每个区间的最大最小值,用线段树实现

参考代码:

  

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 using namespace std;
  5 
  6 #define LL(x) (x<<1)
  7 #define RR(x) (x<<1|1)
  8 #define MID(a,b) (a+((b-a)>>1))
  9 const int N=200005;
 10 #define INF (1<<30)
 11 struct node
 12 {
 13     int lft,rht;
 14     int maxm;
 15     int minm;
 16     int mid()
 17     {
 18         return MID(lft,rht);
 19     }
 20 };
 21 struct Segtree
 22 {
 23     node tree[N*4];
 24     void build(int lft,int rht,int rt)
 25     {
 26         tree[rt].lft=lft;
 27         tree[rt].rht=rht;
 28         tree[rt].maxm=-INF;
 29         tree[rt].minm=INF;
 30         if(lft==rht)
 31         {
 32             scanf("%d",&tree[rt].minm);
 33             tree[rt].maxm=tree[rt].minm;
 34         }
 35         else
 36         {
 37             int mid=tree[rt].mid();
 38             build(lft,mid,LL(rt));
 39             build(mid+1,rht,RR(rt));
 40             tree[rt].maxm=max(tree[LL(rt)].maxm,tree[RR(rt)].maxm);
 41             tree[rt].minm=min(tree[LL(rt)].minm,tree[RR(rt)].minm);
 42         }
 43     }
 44     int querymaxm(int st,int ed,int rt)
 45     {
 46         int lft=tree[rt].lft,rht=tree[rt].rht;
 47         if(st<=lft&&rht<=ed)
 48             return tree[rt].maxm;
 49         else
 50         {
 51             int mid=tree[rt].mid();
 52             int sum1=-INF,sum2=-INF;
 53             if(st<=mid)
 54                 sum1=querymaxm(st,ed,LL(rt));
 55             if(ed>mid)
 56                 sum2=querymaxm(st,ed,RR(rt));
 57             return max(sum1,sum2);
 58         }
 59     }
 60     int queryminm(int st,int ed,int rt)
 61     {
 62         int lft=tree[rt].lft,rht=tree[rt].rht;
 63         if(st<=lft&&rht<=ed)
 64             return tree[rt].minm;
 65         else
 66         {
 67             int mid=tree[rt].mid();
 68             int sum1=INF,sum2=INF;
 69             if(st<=mid)
 70                 sum1=queryminm(st,ed,LL(rt));
 71             if(ed>mid)
 72                 sum2=queryminm(st,ed,RR(rt));
 73             return min(sum1,sum2);
 74         }
 75     }
 76 } seg;
 77 __int64 f(__int64 n)
 78 {
 79     if(n%2)
 80     {
 81         return (n-1)/2*n;
 82     }
 83     return n/2*(n-1);
 84 }
 85 int main()
 86 {
 87     int T;
 88     int i,j;
 89     int n,k;
 90     scanf("%d",&T);
 91     while(T--)
 92     {
 93         __int64 sum=0;
 94         scanf("%d%d",&n,&k);
 95         seg.build(1,n,1);
 96         i=1;
 97         j=1;
 98         while(i<=n&&j<=n)
 99         {
100             int ma=seg.querymaxm(i,j,1);
101             int mi=seg.queryminm(i,j,1);
102             if((ma-mi)>=k)
103             {
104                 sum+=(j-i)+f(j-i);
105                 i++;
106                 for(; i<j; i++)
107                 {
108                     if((seg.querymaxm(i,j,1)-seg.queryminm(i,j,1))<k)
109                     {
110                         sum-=(j-i)+f(j-i);
111                         j++;
112                         break;
113                     }
114                 }
115             }
116             else
117             {
118                 if(j==n)
119                     sum+=(j-i+1)+f(j-i+1);
120                 j++;
121             }
122         }
123         printf("%I64d\n",sum);
124     }
125     return 0;
126 }
View Code

 

posted @ 2015-07-30 09:26  PJQOOO  阅读(244)  评论(0编辑  收藏  举报