做了1001 1003 1005 1006

看题:http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=702

交题: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+Round2B%A3%A9&source=1&searchmode=source

 

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

相关文章: