1. 程式人生 > >2016百度之星 初賽2B ACEF

2016百度之星 初賽2B ACEF

做了1001 1003 1005 1006

1001 區間的價值

亂搞?

做法簡介:有多種做法,主要思想都是先算a[i]作為最小值能管轄的最大左右範圍l[i], r[i],然後求[ l[i], r[i] ]區間內的最大值ma,判斷是否可以更新ans[r[i] - l[i] + 1] = ma*a[i],能更新的話也可以更新更小的區間。

思路過程:

列舉所有區間?n^2,不行。

答案肯定是這樣:大區間的結果小,小區間的結果大,單調的。那麼如果算出了大區間的答案,可以更新到小區間。

發現很多區間的最小值是同一個,如果我們列舉最小值的話,可以求這個最小值管轄的最大左右範圍。

求出了這個範圍的話,我們再求一下這個區間的最大值,就能更新一下這個區間大小的答案,還可以更新小區間大小的答案。

這樣能否得到所有區間大小的最優答案呢?

當然啦,因為我們固定了最小值,這個最小值能對應的最大的最大值被我們找到了,這就是這個最小值的最優答案。我們列舉最小值,就枚舉了所有最優答案。

剩下的問題就是2個:

1.怎麼確定某個最小值的管轄左右範圍;

2.求某個區間的最大值

解:

1.兩種方法:

(1)用DP,從做到右求l[i],從右到左求r[i],求好的值可以拿來用。(我沒用這個方法

(2)用單調棧,二分找到比a[i]左邊的比a[i]小的最右邊的a[j],l[i] = j+1,具體見我的程式碼。

2.兩種方法:

(1)RMQ-ST(我沒用這個

(2)還是用單調棧,要先對區間[Li,Ri]排序,讓Li有序。例如從小到大排,我們從右往左掃,把[Li, n-1]的元素都加入遞減單調棧,二分找下標小於等於Ri的最大的數。具體見我的程式碼。好像有點複雜,還是學一個RMQ-ST比較好。

程式碼(閒著沒事寫了個類看看是不是能看得比較清晰,就寫成這樣了,感覺也不是很清晰。還學了一波函式指標):

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<map>
  9
#include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 14 #define MZ(array) memset(array, 0, sizeof(array)) 15 #define MF1(array) memset(array, -1, sizeof(array)) 16 #define MINF(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define ROF(i,x,y) for(i=(x);i>=(y);i--) 20 #define RD(x) scanf("%d",&x) 21 #define RD2(x,y) scanf("%d%d",&x,&y) 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 23 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) 24 #define WN(x) printf("%d\n",x); 25 #define RE freopen("D.in","r",stdin) 26 #define WE freopen("huzhi.txt","w",stdout) 27 #define MP make_pair 28 #define PB push_back 29 #define PF push_front 30 #define PPF pop_front 31 #define PPB pop_back 32 #define lowbit(x) ((x)&(-x)) 33 template<class T>inline void OA(const T &a,const int &st,const int &ed) { 34 if(ed>=st)cout<<a[st]; 35 int i; 36 FOR(i,st+1,ed)cout<<' '<<a[i]; 37 puts(""); 38 } 39 typedef long long LL; 40 typedef unsigned long long ULL; 41 typedef pair<int,int> PII; 42 const double PI=acos(-1.0); 43 const double EPS=1e-10; 44 inline int sgn(double &x) { 45 if(fabs(x) < EPS)return 0; 46 if(x < 0)return -1; 47 else return 1; 48 } 49 const int INF=0x3f3f3f3f; 50 const int NINF=0x80000001; 51 const int MAXN=111111; 52 const int MAXM=33; 53 const int MOD = 1000000007; 54 55 bool littleThan(int x, int y) { 56 return x<y; 57 } 58 bool biggerThan(int x, int y) { 59 return x>y; 60 } 61 62 class MonoVector { 63 bool (*cmp)(int,int); 64 MonoVector() {} 65 public: 66 vector<PII> q; 67 MonoVector(bool isDecrease) { 68 if(isDecrease) cmp = biggerThan; 69 else cmp = littleThan; 70 q.clear(); 71 } 72 void insert(int id, int value) { 73 while(!q.empty() && cmp(value, q.back().second)) 74 q.pop_back(); 75 q.push_back(MP(id,value)); 76 } 77 ///from right find to left, find the first one witch little/bigger than "value". 78 int LeftStrangeId(int value) { 79 int l = 0,r = q.size()-1; 80 while(l<=r){ 81 int mid = (r-l)/2 + l; 82 if(!cmp(q[mid].second , value)) r = mid - 1; 83 else l = mid + 1; 84 } 85 if(l-1>=0) return q[l-1].first; 86 else return -1; 87 } 88 int getLeftestValueWithIdNoBiggerThan(int id){ 89 int l = 0,r = q.size()-1; 90 while(l<=r){ 91 int mid = (r-l)/2 + l; 92 if(q[mid].first <= id) r = mid - 1; 93 else l = mid + 1; 94 } 95 return q[l].second; 96 } 97 int size() { 98 return q.size(); 99 } 100 void clear(){ 101 q.clear(); 102 } 103 }; 104 105 int n; 106 int a[MAXN]; 107 LL ans[MAXN]; 108 109 void updateAns(int range, LL value){ 110 if(value > ans[range]){ 111 ans[range] = value; 112 if(range>1)updateAns(range - 1, value); 113 } 114 } 115 116 PII lr[MAXN]; 117 bool qcmp(int x,int y){ 118 return lr[x].first < lr[y].first; 119 } 120 121 void farm() { 122 int i,j; 123 MonoVector v = MonoVector(false); 124 REP(i,n) { 125 lr[i].first = v.LeftStrangeId(a[i]) + 1; 126 v.insert(i,a[i]); 127 } 128 v.clear(); 129 ROF(i,n-1,0){ 130 int temp = v.LeftStrangeId(a[i]); 131 if(temp!=-1)lr[i].second=temp - 1; 132 else lr[i].second=n-1; 133 v.insert(i,a[i]); 134 } 135 int q[MAXN]; 136 REP(i,n)q[i]=i; 137 sort(q, q+n, qcmp); 138 v = MonoVector(true); 139 int left = n; 140 ROF(j,n-1,0){ 141 i = q[j]; 142 while(lr[i].first < left){ 143 left --; 144 v.insert(left , a[left]); 145 } 146 int ma = v.getLeftestValueWithIdNoBiggerThan(lr[i].second); 147 // printf("%d [%d,%d], mi=%d, ma=%d, %d,%d\n",i,lr[i].first, lr[i].second, a[i], ma, a[i]*ma, lr[i].second - lr[i].first+1); 148 updateAns(lr[i].second - lr[i].first + 1 , 1LL*ma*a[i]); 149 } 150 151 } 152 153 int main() { 154 int i; 155 while(RD(n)!=EOF) { 156 MZ(ans); 157 REP(i,n) RD(a[i]); 158 farm(); 159 FOR(i,1,n)cout<<ans[i]<<endl; 160 } 161 return 0; 162 }
View Code

(這題我自己沒想出來,看別人題解,怎麼全會用那個DP求l[i] r[i],for裡面套while,看起來像O(n^2)的啊,想了一下發現好像並不是。我還是要學習一個。)

1003 瞬間移動 

寫個暴力打表找規律,發現是組合數。

使m<n(不小於的話就交換一下,對稱的), f(m,n) = C(m+n-2, m-1)

然後就變成怎麼求大組合數取模了。這題的好像還不是很大,可以直接用逆元。再大的話要用Lucas定理加逆元了。

程式碼:

 1 //#pragma comment(linker, "/STACK:102400000,102400000")
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<iostream>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<cmath>
 8 #include<map>
 9 #include<set>
10 #include<stack>
11 #include<queue>
12 using namespace std;
13 
14 #define MZ(array) memset(array, 0, sizeof(array))
15 #define MF1(array) memset(array, -1, sizeof(array))
16 #define MINF(array) memset(array, 0x3f, sizeof(array))
17 #define REP(i,n) for(i=0;i<(n);i++)
18 #define FOR(i,x,n) for(i=(x);i<=(n);i++)
19 #define ROF(i,x,y) for(i=(x);i>=(y);i--)
20 #define RD(x) scanf("%d",&x)
21 #define RD2(x,y) scanf("%d%d",&x,&y)
22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
23 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
24 #define WN(x) printf("%d\n",x);
25 #define RE  freopen("D.in","r",stdin)
26 #define WE  freopen("huzhi.txt","w",stdout)
27 #define MP make_pair
28 #define PB push_back
29 #define PF push_front
30 #define PPF pop_front
31 #define PPB pop_back
32 #define lowbit(x) ((x)&(-x))
33 template<class T>inline void OA(const T &a,const int &st,const int &ed) {
34     if(ed>=st)cout<<a[st];
35     int i;
36     FOR(i,st+1,ed)cout<<' '<<a[i];
37     puts("");
38 }
39 typedef long long LL;
40 typedef unsigned long long ULL;
41 const double PI=acos(-1.0);
42 const double EPS=1e-10;
43 inline int sgn(double &x) {
44     if(fabs(x) < EPS)return 0;
45     if(x < 0)return -1;
46     else return 1;
47 }
48 const int INF=0x3f3f3f3f;
49 const int NINF=0x80000001;
50 const int MAXN=111111;
51 const int MAXM=33;
52 const int MOD = 1000000007;
53 
54 int n,m;
55 
56 LL PowerMod(LL a, LL b) {
57     LL tmp = a, ret = 1;
58     while (b) {
59         if (b & 1) ret = ret * tmp % MOD;
60         tmp = tmp * tmp % MOD;
61         b >>= 1;
62     }
63     return ret;
64 }
65 
66 LL calC(LL n,LL m){
67     m=n-m>m?m:n-m;
68     LL up=1,down=1;
69     int i;
70     for(i=1;i<=m;i++){
71         down*=i;
72         down%=MOD;
73         up*=(n-i+1);
74         up%=MOD;
75     }
76     return (up*PowerMod(down,MOD-2))%MOD;
77 }
78 
79 LL Lucas(LL n, LL m) {
80     if(m==0)return 1;
81     return (Lucas(n/MOD, m/MOD)*calC(n%MOD, m%MOD))%MOD;
82 }
83 
84 inline LL farm(){
85     int i,j;
86     if(n<m)swap(n,m);
87     ///f(x,y) = C(x+y-2,x-1)   (x>y)
88     LL re = 1;
89     return Lucas(n+m-2,n-1);
90 }
91 
92 int main(){
93     while(RD2(n,m)!=EOF){
94         n--;m--;
95         cout<<farm()<<endl;
96     }
97     return 0;
98 }
View Code

上面好像是用^(n-2)的那種逆元,下面我又搞了一個exgcd逆元的:

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 /**Header!**/ //{
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<cstring>
  7 #include<algorithm>
  8 #include<cmath>
  9 #include<map>
 10 #include<set>
 11 #include<stack>
 12 #include<queue>
 13 using namespace std;
 14 
 15 #define MZ(array) memset(array, 0, sizeof(array))
 16 #define MF1(array) memset(array, -1, sizeof(array))
 17 #define MINF(array) memset(array, 0x3f, sizeof(array))
 18 #define REP(i,n) for(i=0;i<(n);i++)
 19 #define FOR(i,x,n) for(i=(x);i<=(n);i++)
 20 #define ROF(i,x,y) for(i=(x);i>=(y);i--)
 21 #define RD(x) scanf("%d",&x)
 22 #define RD2(x,y) scanf("%d%d",&x,&y)
 23 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
 24 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
 25 #define WN(x) printf("%d\n",x);
 26 #define RE  freopen("D.in","r",stdin)
 27 #define WE  freopen("huzhi.txt","w",stdout)
 28 #define MP make_pair
 29 #define PB push_back
 30 #define PF push_front
 31 #define PPF pop_front
 32 #define PPB pop_back
 33 #define lowbit(x) ((x)&(-x))
 34 #define cindiao ios_base::sync_with_stdio(0)
 35 #define fcout(x,y) cout << fixed << setprecision(x) << (y) << endl
 36 typedef long long LL;
 37 typedef unsigned long long ULL;
 38 typedef pair<int,int> PII;
 39 template<class T>inline void OA(const T &a,const int &st,const int &ed) {
 40     if(ed>=st)cout<<a[st];
 41     int i;
 42     FOR(i,st+1,ed)cout<<' '<<a[i];
 43     puts("");
 44 }
 45 template <class T> inline T quickPow(T p,T e,const T &M){
 46     LL ret = 1;
 47     for(; e > 0; e >>= 1){
 48         if(e & 1) ret = (ret * p) % M;
 49         p = (p * p) % M;
 50     } return (T)ret;
 51 }
 52 template <class T> inline T gcd(const T &a,const T &b){return (b==0) ? a : gcd(b,a%b);}
 53 template <class T> inline T niyuan(const T &a, const T &M){return quickPow(a,M-2,M);}
 54 template <class T> inline T exgcd(const T &a,const T &b,T &x,T &y) {
 55     if (!b) {x=1,y=0;return a;}
 56     T ret=exgcd(b,a%b,x,y), t;
 57     t=x,x=y,y=t-a/b*y;
 58     return ret;
 59 }
 60 template <class T> inline T niyuanex(const T &a, const T &M){
 61     T x,y;
 62     exgcd(a,M,x,y);
 63     return (x+M)%M;
 64 }
 65 inline LL calC(const int &n,int m,const LL &MOD){
 66     m=(n-m>m)?m:(n-m);
 67     LL up=1,down=1;
 68     int i;
 69     for(i=1;i<=m;i++){
 70         down*=i;
 71         down%=MOD;
 72         up*=(n-i+1);
 73         up%=MOD;
 74     }
 75     return (up*niyuanex(down, MOD))%MOD;
 76 }
 77 inline LL Lucas(const int &n,const int &m, const int &MOD) {
 78     if(m==0)return 1;
 79     return (1LL * Lucas(n/MOD, m/MOD, MOD)*calC(n%MOD, m%MOD, MOD))%MOD;
 80 }
 81 const int gx[4] = {-1,0,1,0};
 82 const int gy[4] = {0,1,0,-1};
 83 const double PI=acos(-1.0);
 84 //}
 85 const double EPS=1e-10;
 86 inline int sgn(double &x) {
 87     if(fabs(x) < EPS)return 0;
 88     if(x < 0)return -1;
 89     else return 1;
 90 }
 91 const int INF=0x3f3f3f3f;
 92 const int NINF=0x80000001;
 93 const int MAXN=111111;
 94 const int MAXM=33;
 95 const int MOD = 1000000007;
 96 
 97 int n,m;
 98 
 99 inline LL farm(){
100     int i,j;
101     if(n<m)swap(n,m);
102     ///f(x,y) = C(x+y-2,x-1)   (x>y)
103     LL re = 1;
104     return Lucas(n+m-2,n-1,MOD);
105 }
106 
107 int main(){
108     while(RD2(n,m)!=EOF){
109         n--;m--;
110         cout<<farm()<<endl;
111     }
112     return 0;
113 }
View Code

1005 區間交

優先佇列題。

把區間[Li,Ri]按照Li從小到大排序。

然後依次把區間加入候選集,把他們的Ri加入優先佇列,記住最小的Ri。

加到夠k個以後,每次就要看是否能更新答案了。

k個區間的交集,區間[L,R],L就是最新加入的那個Li,R就是記著的最小的Ri。

如果光用優先佇列來找最小Ri的話,會超時,我們來優化一下,就只在優先佇列中存最大的k個Ri,不存太多的Ri。

程式碼:

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 #include<queue>
 12 using namespace std;
 13 
 14 #define MZ(array) memset(array, 0, sizeof(array))
 15 #define MF1(array) memset(array, -1, sizeof(array))
 16 #define MINF(array) memset(array, 0x3f, sizeof(array))
 17 #define REP(i,n) for(i=0;i<(n);i++)
 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++)
 19 #define ROF(i,x,y) for(i=(x);i>=(y);i--)
 20 #define RD(x) scanf("%d",&x)
 21 #define RD2(x,y) scanf("%d%d",&x,&y)
 22 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
 23 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
 24 #define WN(x) printf("%d\n",x);
 25 #define RE  freopen("D.in","r",stdin)
 26 #define WE  freopen("huzhi.txt","w",stdout)
 27 #define MP make_pair
 28 #define PB push_back
 29 #define PF push_front
 30 #define PPF pop_front
 31 #define PPB pop_back
 32 #define lowbit(x) ((x)&(-x))
 33 template<class T>inline void OA(const T &a,const int &st,const int &ed) {
 34     if(ed>=st)cout<<a[st];
 35     int i;
 36     FOR(i,st+1,ed)cout<<' '<<a[i];
 37     puts("");
 38 }
 39 typedef long long LL;
 40 typedef unsigned long long ULL;
 41 const double PI=acos(-1.0);
 42 const double EPS=1e-10;
 43 inline int sgn(double &x) {
 44     if(fabs(x) < EPS)return 0;
 45     if(x < 0)return -1;
 46     else return 1;
 47 }
 48 const int INF=0x3f3f3f3f;
 49 const int NINF=0x80000001;
 50 const int MAXN=111111;
 51 const int MAXM=33;
 52 const int MOD = 1000000007;
 53 
 54 struct Node {
 55     int l,r;
 56     inline bool operator<(
            
           

相關推薦

2016 初賽2B ACEF

做了1001 1003 1005 1006 1001 區間的價值 亂搞? 做法簡介:有多種做法,主要思想都是先算a[i]作為最小值能管轄的最大左右範圍l[i], r[i],然後求[ l[i], r[i] ]區間內的最大值ma,判斷是否可以更新ans[r[i] - l[i] + 1] = ma

2016 初賽2A ABEF

只做了1001 1002 1005 1006。剩下2題可能以後補? http://acm.hdu.edu.cn/search.php?field=problem&key=2016%22%B0%D9%B6%C8%D6%AE%D0%C7%22+-+%B3%F5%C8%FC%A3%A8Astar+Roun

2016初賽Astar Round2B

題意: 定義一個區間的價值為區間的最大數*最小數。現給了n(1≤n≤100000)個數,問1~n長度的最大價值分別是多少。 題解:     用兩個線段樹以及快排的思想可以在O(nlog(n))的時間解決該題。     首先用線段樹找到一個區間[L,R]的最小值位置為a與最大

2014初賽第一場部分題解

ref 連接 又是 百度之星 虛擬 子節點 get content trac 代碼太醜就不貼了。,又是一篇無責任民科的題解。。 HDU 4828 Grids 看了一下跟卡特蘭數差點兒相同就猜了一下,詳細為啥我也不知道。。然後有除法套個逆元。。 HDU 4830

2017初賽A 今夕何夕

ucc others rdquo while main cli for 表示 script 今夕何夕 Accepts: 1345 Submissions: 5533 Time Limit: 2000/1000 MS (Java/Others)

2017初賽A 度度熊的01世界

content scanf output bar imp boa 世界 clock other 度度熊的01世界 Accepts: 967 Submissions: 3064 Time Limit: 2000/1000 MS (Java/Ot

初賽(A)——T1

printf input acf 一行 while wid 3的倍數 main cli 小C的倍數問題 Problem Description 根據小學數學的知識,我們知道一個正整數x是3的倍數的條件是x每一位加起來的和是3的倍數。反之,如果一個數每一位加起來是3

初賽A hdu6113

clas define bsp sizeof truct front 數量 tac code 度度熊的01世界 題意:中文題 思路:在最外面加一圈0,然後判聯通塊的個數,1的聯通塊數量只能是1,否則輸出-1,0的聯通塊只能是1或者2,否則輸出-1 AC代碼: #inclu

2017初賽B Chess

tput long put 它的 ucc others style info 同一行 Chess Accepts: 1805 Submissions: 5738 Time Limit: 2000/1000 MS (Java/Others)

hdu 6119 初賽

break bool class push_back 合並 ring tdi hdu 天數 去重合並,以某個點為起點,向後二分到最後一個滿足未簽到天數<=m的點。 二分時的查詢有很多方法,可以用線段樹,dp,前綴數組等等。比賽時沒有想到前綴數組,就用來dp來完成查詢,

HDU 6119 2017初賽B 小小粉絲度度熊 (二分)

端點 mission make miss 情況 others sin time 天都 小小粉絲度度熊 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To

(最小費用流)hdu 6118(2017初賽B 1005) 度度熊的交易計劃

ios rsh des pty rank tom mis 註意 pan 度度熊的交易計劃 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su

2017初賽(A)1001,1005,1006解題報告

百度 src cout lose 初賽 bool amp spa span 1001 小C的倍數問題 純簽到題,求p-1的因數個數,暴力枚舉即可 1 #include<bits/stdc++.h> 2 using namespace std; 3 in

hdu 6116 路徑計數 初賽B補--計數問題+NTT

alt ons 計數問題 init uic 下標 urn spa http 題意和這個例題很像。交錯排列問題。直接用三次NTT優化 #include <bits/stdc++.h> const long long MOD = 998244353; co

【2018初賽(A)】1002 度度熊學隊列

std php begin include push_back targe ref 使用 sin 題目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6375 Knowledge Point:   STL - map:ht

2016複賽 1003 拍照 優先佇列

2016"百度之星" - 複賽(Astar Round3)  Ended  2016-05-29 14:00:00 - 2016-05-29 17:00:00 Current Time: 00:46:02 SolvedPro.IDTitleRatio(Accepted / Submi

2016 資格賽ABCDE

A.題意:定義小寫字母組成的字串的雜湊值,為(單個字母的ASCII碼減去28)的乘積。給出長度最多為100000的字串和最多1000次詢問,每次詢問[L,R]之間的字串的雜湊值。 題解: 有多種做法。 1.逆元  2.線段樹  3.分塊陣列 1.逆元做法:因為每次求區間[L,R]乘積,可以

2016 - 資格賽 Astar Round1 - 模擬+線段樹+乘法逆元

                Problem A   Accepts:

2016資格賽題解

1 #include<stdio.h> 2 #include<string.h> 3 #include<map> 4 #include<string> 5 using namespace std; 6 7 struc

初賽2 瞬間轉移 HDU 5698 (組合數+逆元)

大意:有一個無限大的矩形,初始時你在左上角(即第一行第一列),每次你都可以選擇一個右下方格子,並瞬移過去(如從下圖中的紅色格子能直接瞬移到藍色格子),求到第n行第m列的格子有幾種方案,答案對10000