Bestcoder #29

2015-02-07 21:34:53

总结:这场开场有点慢了... 还好前三题都是可做题。搞了三题+1hack,rank30。

A:因为是幂的比较,所以考虑到两边取log,然后直接比较即可。但是卡了下精度,要先看是否相等(fabs()< 1e-10),然后再判大小。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 
27 double a,b,c,d;
28 double A,B;
29 
30 int main(){
31     while(scanf("%lf%lf%lf%lf",&a,&b,&c,&d) != EOF){
32         A = 1.0 * b * log(1.0 * a);
33         B = 1.0 * d * log(1.0 * c);
34         if(fabs(A - B) < 1e-10) printf("=\n");
35         else if(A > B) printf(">\n");
36         else printf("<\n");
37     }
38     return 0;
39 }
View Code

 

B:因为k很大,而且有模数,所以是比较明显的快速幂题。考虑到是不断地取最大的两个数,然后相加... 于是我们就有这样的转移方程,最大的两个数赋为v[1],v[2],转移方程:

 ×  =  需要注意的一点是防止超int,全部开成 long long

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
21 #define MP(a,b) make_pair(a,b)
22 
23 typedef long long ll;
24 typedef pair<int,int> pii;
25 const int INF = (1 << 30) - 1;
26 const ll mod = 10000007;
27 
28 ll n,k,val[100010];
29 
30 struct Mx{
31     ll a[3][3];
32     void clear(){ memset(a,0,sizeof(a));}
33     void stand(){ memset(a,0,sizeof(a)); for(int i = 0; i < 3; ++i) a[i][i] = 1;}
34     Mx operator * (Mx b){
35         Mx c; c.clear();
36         for(int i = 0; i < 3; ++i){
37             for(int j = 0; j < 3; ++j){
38                 for(int k = 0; k < 3; ++k){
39                     c.a[i][j] = (c.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
40                 }
41             }
42         }
43         return c;
44     }
45 };
46 
47 Mx Q_pow(ll num){
48     Mx t; t.clear();
49     Mx res; res.stand();
50     t.a[0][1] = 1;
51     t.a[1][0] = t.a[1][1] = 1;
52     t.a[2][0] = t.a[2][1] = t.a[2][2] = 1;
53     while(num){
54         if(num & 1) res = res * t;
55         t = t * t;
56         num >>= 1;
57     }
58     return res;
59 }
60 
61 int main(){
62     while(scanf("%I64d%I64d",&n,&k) != EOF){
63         REP(i,n) scanf("%I64d",&val[i]);
64         ll sum = 0;
65         sort(val,val + n);
66         for(int i = 0; i < n - 2; ++i) sum = (sum + val[i]) % mod;
67         Mx ans;
68         ans.clear();
69         ans.a[0][0] = val[n - 2];
70         ans.a[1][0] = val[n - 1];
71         ans.a[2][0] = val[n - 1] + val[n - 2];
72         ans = Q_pow(k) * ans;
73         printf("%I64d\n",(ans.a[2][0] + sum) % mod);
74     }
75     return 0;
76 }
View Code

 

C:一开始想暴力搞... 后来发现涉及区间询问,果断上了线段树

  这题有两个模型:小白书的贪心例题(区间相关问题),线段树优化。

  首先按照询问区间的右端点进行排序,然后逐个处理询问,逐个扫描序列,保存下每个数的最右位置(其实从左到右扫的话就是不断更新各个数的位置)

  对于每个询问,比如是[4,10],区间长度是7,那么我们只要知道1~7这些数的最右位置是否都在[4,10]内就可以了,再进一步只要知道1~7的最小位置是否是4即可。(思考)

  直接暴力必定超时,只要加一颗线段树来维护区间最小值即可。(赛后数据改大了... QAQ)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #include <queue>
 10 #include <string>
 11 #include <iostream>
 12 #include <algorithm>
 13 using namespace std;
 14 
 15 #define MEM(a,b) memset(a,b,sizeof(a))
 16 #define REP(i,n) for(int i=0;i<(n);++i)
 17 #define REV(i,n) for(int i=(n-1);i>=0;--i)
 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
 20 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
 21 #define MP(a,b) make_pair(a,b)
 22 
 23 typedef long long ll;
 24 typedef pair<int,int> pii;
 25 const int INF = (1 << 30) - 1;
 26 const int MAXN = 1000010;
 27 
 28 int n,m;
 29 int val[MAXN];
 30 int ans[MAXN];
 31 int tmin[MAXN];
 32 int L,R,A,C;
 33 
 34 struct edge{
 35     int l,r,id;
 36 }e[MAXN];
 37 
 38 inline int Read(){
 39     int x = 0,f = 1;char ch = getchar();
 40     while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();}
 41     while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
 42     return x * f;
 43 }
 44 
 45 bool cmp(edge a,edge b){
 46     if(a.r == b.r)
 47         return a.l < b.l;
 48     return a.r < b.r;
 49 }
 50 
 51 struct SMT{
 52     int tmin[MAXN << 2];
 53     void clear(){
 54         memset(tmin,0,sizeof(tmin));
 55     }
 56     void Update(int p,int l,int r){
 57         if(l == r){
 58             tmin[p] = C;
 59             return;
 60         }
 61         int mid = getmid(l,r);
 62         if(val[C] <= mid) Update(p << 1,l,mid);
 63         else Update(p << 1|1,mid + 1,r);
 64         tmin[p] = min(tmin[p << 1],tmin[p << 1|1]);
 65     }
 66     int Query(int p,int l,int r){
 67         if(1 <= l && r <= R)
 68             return tmin[p];
 69         int mid = getmid(l,r);
 70         int res = INF;
 71         if(1 <= mid) res = min(res,Query(p << 1,l,mid));
 72         if(R > mid) res = min(res,Query(p << 1|1,mid + 1,r));
 73         return res;
 74     }
 75 }smt;
 76 
 77 int main(){
 78     while(scanf("%d%d",&n,&m) != EOF){
 79         smt.clear();
 80         FOR(i,1,n) val[i] = Read();
 81         FOR(i,1,m){
 82             e[i].l = Read();
 83             e[i].r = Read();
 84             e[i].id = i;
 85         }
 86         sort(e + 1,e + m + 1,cmp);
 87         C = 1;
 88         FOR(i,1,m){
 89             for(; C <= e[i].r; ++C)
 90                 smt.Update(1,1,n);
 91             R = e[i].r - e[i].l + 1;
 92             int res = smt.Query(1,1,n);
 93             if(res == e[i].l) ans[e[i].id] = 1;
 94             else ans[e[i].id] = 0;
 95         }
 96         FOR(i,1,m){
 97             if(ans[i]) printf("YES\n");
 98             else printf("NO\n");
 99         }
100     }
101     return 0;
102 }
View Code

 

转载于:https://www.cnblogs.com/naturepengchen/articles/4279600.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值