• [单调栈]1156E Special Segments of Permutation


    题意:给一个1-n的排列, 你需要求出有多少个区间满足a[l] + a[r] = max(a[l] - a[r]);

     解题思路

    首先记录每个数字的下标

    然后用单调栈维护以 a[i] 为最高点的区间

    然后枚举 a[i] 区间内较短一侧的数

    因为1 - n 排列数值唯一且已经记录了位置, 所以可以 O(1) 的求出 (a[i] - 小区间内数 )是否在右侧区间中, 统计得解


    代码:

    /*
        Zeolim - An AC a day keeps the bug away
    */
    
    //pragma GCC optimize(2)
    #include <cstdio>
    #include <iostream>
    #include <bitset>
    #include <cstdlib>
    #include <cmath>
    #include <cctype>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <set>
    #include <sstream>
    #include <map>
    #include <ctime>
    #include <vector>
    #include <fstream>
    #include <list>
    #include <iomanip>
    #include <numeric>
    #include <ext/pb_ds/tree_policy.hpp>
    #include <ext/pb_ds/assoc_container.hpp>
    using namespace std;
    //using namespace __gnu_pbds;
    //typedef tree <long long, null_type, less <long long>, rb_tree_tag, tree_order_statistics_node_update> rbtree;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    #define mp(x, y) make_pair(x, y)
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const int INF = 0x3f3f3f3f;
    const int MAXN = 1e6 + 10;
    const ll MOD = 1e9 + 7;
    
    int arr[MAXN] = {0};
    
    struct node
    {
    	int l, r, loc;
    }pos[MAXN];
    
    int main()
    {
        //ios::sync_with_stdio(false);
        //cin.tie(0);     cout.tie(0);
        //freopen("D://test.in", "r", stdin);
        //freopen("D://test.out", "w", stdout);
    	
    	int n;
    
    	cin >> n;
    
    	for(int i = 1; i <= n; ++i)
    		cin >> arr[i], pos[i].l = i, pos[i].r = i, pos[arr[i]].loc = i;
    
    	stack <int> ST;
    	
    	arr[0] = arr[n + 1] = INF;
    	 
    	ST.push(0);
    
    	for(int i = 1; i <= n; ++i) //单调栈求区间
    	{
    		while(!ST.empty() && arr[i] > arr[ST.top()]) ST.pop();
    		pos[i].l = ST.top() + 1;
    		ST.push(i);
    	}
    
    	while(!ST.empty()) ST.pop();
    
    	ST.push(n + 1);
    	
    	for(int i = n; i >= 1; --i)
    	{
    		while(!ST.empty() && arr[i] > arr[ST.top()]) ST.pop();
    		pos[i].r = ST.top() - 1;
    		ST.push(i);
    	}
    
    	int ans = 0;
    
    	for(int i = 1; i <= n; ++i)
    	{
    		if(i - pos[i].l <= pos[i].r - i) 
    		{
    			for(int j = pos[i].l; j < i; ++j) //枚举合法
    				if(pos[arr[i] - arr[j]].loc > i && pos[arr[i] - arr[j]].loc <= pos[i].r)
    					++ans;
    		}
    		else
    		{
    			for(int j = i + 1; j <= pos[i].r; ++j)
    				if(pos[arr[i] - arr[j]].loc < i && pos[arr[i] - arr[j]].loc >= pos[i].l)
    					++ans;
    		}
    	}
    
    	cout << ans << '
    ';
    
        return 0;
    }
    
  • 相关阅读:
    python机器学习系列之环境搭建
    github 出现 Permission denied (publickey)的解决
    Eclipse添加Web和java EE插件
    GNU Make 学习系列一:怎样写一个简单的Makefile
    GTK+编程概述
    SpringBoot导出excel数据报错Could not find acceptable representation
    Postman测试上传MultipartFile文件
    idea 代码没有被svn控制
    FPGA基础学习(1) -- FFT IP核(Quartus)
    markdown使用小结
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270366.html
Copyright © 2020-2023  润新知