上海五校联赛 H 调和序列

中文题意不解释

一开始以为是个线段树之类的数据结构 毕竟还有查询

但是算了一下时间复杂度发现直接暴力就可以

O(n*sqrt(n)*sqrt(n)*log(sqrt(n))) 大概只有2e6的复杂度

对于每一个n对每个k≤sqrt(n)预处理排序 大于的部分直接计算就可以

反正还是很水的了

记得M是构造两棵线段树 但是没来得及做 晚上有时间的话补上

 

 1 #include<bits/stdc++.h>
 2 #define cl(a,b) memset(a,b,sizeof(a))
 3 #define debug(a) cerr<<#a<<"=="<<a<<endl
 4 using namespace std;
 5 typedef long long ll;
 6 typedef pair<int,int> pii;
 7 
 8 const int maxn=2e4+10;
 9 
10 int n,m;
11 int a[maxn];
12 vector<int>ans[205]; //也不知道会不会爆内存 就直接用vector了
13 
14 bool cmp(int a,int b)
15 {
16     return a>b;
17 }
18 
19 void init()
20 {
21     for(int i=1;i<=sqrt(n);i++) //预处理sqrt(n)的部分
22     {
23         ans[i].clear();
24         for(int j=0;j<n;j+=i)
25         {
26             ans[i].push_back(a[j]);
27         }
28         sort(ans[i].begin(),ans[i].end(),cmp);
29     }
30 }
31 
32 int solve(int k,int s)
33 {
34     if(k <= sqrt(n)) //对于≤sqrt(n)的k值直接查询
35     {
36         if(s>ans[k].size()) return -1;
37         else return ans[k][s-1];
38     }
39     else //大于的直接暴力 反正也没几个数
40     {
41         vector<int>tmp;
42         tmp.clear();
43         for(int i=0;i<n;i+=k)
44         {
45             tmp.push_back(a[i]);
46         }
47         sort(tmp.begin(),tmp.end(),cmp);
48         if(s>tmp.size()) return -1;
49         else return tmp[s-1];
50     }
51 }
52 
53 int main()
54 {
55     int T;
56     scanf("%d",&T);
57     while(T--)
58     {
59         cl(a,0);
60         scanf("%d%d",&n,&m);
61         for(int i=0;i<n;i++)
62         {
63             scanf("%d",&a[i]);
64         }
65         init(); //预处理
66         while(m--)
67         {
68             int k,s;
69             scanf("%d%d",&k,&s);
70             printf("%d\n",solve(k,s));
71         }
72     }
73     return 0;
74 }/*
75 
76 1
77 5 2
78 2 5 3 4 1
79 2 4
80 2 1
81 
82 */

 

posted @ 2017-07-09 18:09  良将ℓ  阅读(267)  评论(0编辑  收藏  举报