zoukankan      html  css  js  c++  java
  • 模拟总结(奶牛排队)

    第一题,luogu原题。。。堆排序。。。二分也可。

    第二题。。。。不会,瞎搞。。。直到提交前还在反复测数据。

    维护一个单调递减的单调队列/单调栈 每次插入高度时 若队中已有高度低于这头牛的牛 就判断队中牛能向左延伸到的那头牛能否被这头牛延伸到 (特判高度相等的) 然后每个位置计算答案并更新。

    维护一个Node的单调栈,Node各元素的含义为:

    v,p:该Node代表的值(value)和其在序列中所在的位置(position)

    mv,mp:对于所有以该元素为开头的合法序列,结尾的最大值及其所在位置

    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #define rep(id,a,b) for(int id = (a);id < (b);id++)
    #define irep(id,a,b) for(int id = (a);id > (b);id--)
    #define reset(arr,c) memset(arr,c,sizeof(arr))
    #define N 100005
    typedef long long int64;
    using namespace std;
    int n,h[N];
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    void input() {
    	n = read();
    	rep (i, 0, n)
    	h[i] = read();
    }
    struct Node {
    	int v, p, mv, mp;
    	Node (int _v, int _p, int _mv, int _mp) :
    	v (_v), p (_p), mv (_mv), mp (_mp) {}
    };
    int solve() {
    	int ans  = 0;
    	stack<Node> st;
    	irep (i, n - 1, -1) {
    		int m = h[i], p = i;
    		while (!st.empty() && h[i] < st.top().v) {
    			if (st.top().mv > m) {
    				m = st.top().mv;
    				p = st.top().mp;
    			}
    			st.pop();
    		}
    		st.push (Node (h[i], i, m, p) );
    		ans = max (ans, p - i + 1);
    	}
    	return (ans == 1) ? 0 : ans;
    }
    int main() {
    	input();
    	printf ("%d
    ", solve() );
    	return 0;
    }
    

      

    第三题:

    可以进行二分,二分算法。

    用前缀和将环一分为二,再枚举答案。 

    或者我们可以这样。 
    把这个圆顺时针做前缀和,然后枚举两边的值并比较即可。大概O(2n)。

    下面是个O(n)算法,很妙。

    可以把这个圆看作一条直线
    设立一个l,一个r分别指向这条直线,l到r之间的距离为x
    那么最右值肯定是越靠近总和除以2越好
    1 2 3 4 5 … n
    l r
    那么,当x小于sum/2时,r往右靠,(一遍做一边打擂),如果x大于sum/2,那么l向右靠,当r到n时,循环结束,答案得出 。

  • 相关阅读:
    JavaScript基础语法及字符串相关方法(1)
    matplotlib实现三维柱状图
    前端入门CSS(3)
    博客页面练习
    前端入门CSS(2)
    前端入门CSS(1)
    前端入门html(表单)
    Longest Palindromic Substring
    Wildcard Matching
    Spiral Matrix II
  • 原文地址:https://www.cnblogs.com/excellent-zzy/p/10749601.html
Copyright © 2011-2022 走看看