做了1001 1003 1005 1006
看题:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=702
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 }