最近真是太废柴了,题没做几道,也没学什么新知识,多校做了三场也没总结~诶!好好学吧!
多校第一场感觉被完虐...orz...
Hdu 5288 OO’s Sequence
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288
题意:
f(l,r)表示满足ai%aj≠0的i的个数(i∈[l,r],j∈[l,r],j≠i)
已知n个数 a1,a2,…an,求
思路:这个题实质是对于一个包含ai的区间,如果ai符合上述条件,即对于aj,ai%aj≠0,则aj不是ai的因子
对于每一个数ai,分别向左向右去找离它最近的因子的下标L[i],R[i],ans+=(i-L[i])*(R[i]-i);
参考代码:
1 #include2 #include<string.h> 3 #include 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 }
Assignment
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5289
题意: 求有多少个区间满足区间内任意两个数的差值小于k
思路: 区间内最大差值为区间内最大值与最小值的差,只要其差满足条件,
则该区间符合条件左区间l先固定,去找最大区间符合条件,即[l,r-1]符合,
那么ans+=((r−l)/2)+r−l,然后r不变,l不断加1,直到找到符合条件的 [l,r]为止,
那么[l,j-1]会被重复算,需要减掉.
为了更快的查询每个区间的最大最小值,用线段树实现
参考代码:
1 #include2 #include 3 #include 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 ) 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 }