• [权值线段树] 1163B2 Cat Party (Hard Edition)


    题意: 给一序列串求最大x 有 x前删除一个值后每个值出现次数相同

     解法: B1是小范围版, 只要枚举数字就行

    B2用权值线段树记录最大最小出现次数, 出现n次的数有几个, 结合B1的规律(在代码里↓)写即可 

    代码

    /*
        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>
    #define max(a, b) a > b ? a : b
    #define min(a, b) a > b ? b : a
    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;
    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}, cnt[MAXN] = {0}, rnt[MAXN] = {0}, num;
    
    struct node
    {
        int fst, lst, val, mival;
    }sgtree[MAXN * 4];
    
    void build(int now, int fst, int lst)
    {
        sgtree[now].fst = fst, sgtree[now].lst = lst;
        if(fst == lst) { sgtree[now].val = 0, sgtree[now].mival = INF; return ; }
        int mid = (fst + lst) / 2;
        build(now * 2, fst, mid);
        build(now * 2 + 1, mid + 1, lst);
        sgtree[now].val = max(sgtree[now * 2].val, sgtree[now * 2 + 1].val);
        sgtree[now].mival = min(sgtree[now * 2].mival, sgtree[now * 2 + 1].mival);
    }
    
    int ask(int now, int fst, int lst)
    {
        if(fst <= sgtree[now].fst && lst >= sgtree[now].lst) return sgtree[now].val;
        int mid = (sgtree[now].fst + sgtree[now].lst) / 2;
        int rval = -(1 << 30);
        if(fst <= mid)  rval = max(rval, ask(now * 2, fst, lst));
        if(lst > mid) rval = max(rval, ask(now * 2 + 1, fst, lst));
        return rval;
    }
    
    int askmi(int now, int fst, int lst)
    {
        if(fst <= sgtree[now].fst && lst >= sgtree[now].lst) return sgtree[now].mival;
        int mid = (sgtree[now].fst + sgtree[now].lst) / 2;
        int rval = INF;
        if(fst <= mid)  rval = min(rval, askmi(now * 2, fst, lst));
        if(lst > mid) rval = min(rval, askmi(now * 2 + 1, fst, lst));
        return rval;
    }
    
    void change(int now, int pos, int rval)
    {
        if(sgtree[now].fst == sgtree[now].lst) { sgtree[now].val = sgtree[now].mival = rval; return; }
        int mid = (sgtree[now].fst + sgtree[now].lst) / 2;
        if(pos <= mid) change(now * 2, pos, rval);
        else change(now * 2 + 1, pos, rval);
        sgtree[now].val = max(sgtree[now * 2].val, sgtree[now * 2 + 1].val);
        sgtree[now].mival = min(sgtree[now * 2].mival, sgtree[now * 2 + 1].mival);
    }
    
    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, len;
    
        cin >> n;
    
        for(int i = 1; i <= n; ++i)
            cin >> arr[i], len = max(len, arr[i]);
        
        build(1, 1, len);
        
        int ans = 0;
        
        //cnt记录 x出现的次数 rnt记录出现 x次的数字有几个 num记录当前一共出现数字个数
    
        for(int i = 1; i <= n; ++i)
        {
        	int x = arr[i];
    		
            if(!cnt[x]) ++num;
    		
            ++cnt[x], ++rnt[cnt[x]];
    		
    	    if(i != 1)
    		    --rnt[cnt[x] - 1];
    		
            change(1, arr[i], cnt[arr[i]]);
    
            int mx = ask(1, 1, len), mi = askmi(1, 1, len); //求最大最小值
            
            if(mx == mi && rnt[mx] == 1)  ans = i; //就一个数
            
            else if(mx == mi && mi == 1)  ans = i; //一堆数但是出现次数都是1
            
            else if(mi == 1 && rnt[1] == 1 && rnt[mx] == num - 1) ans = i; //只有一个数出现一次 
            
            else if(mx - mi == 1 && rnt[mx] == 1) ans = i;//最多次比其他都多1
    	}
    	
    	cout << ans << '
    ';
            
        
        return 0;
    }
  • 相关阅读:
    快速瘦身大米瘦身法 健康程序员,至尚生活!
    20个生活小习惯"狠"减肥 健康程序员,至尚生活!
    橙子帮助减肥,谁都可以轻松做到 健康程序员,至尚生活!
    10个减肥小贴士,日常必备哦! 健康程序员,至尚生活!
    有源淹没分析arcgis_ArcGIS水文分析实战教程(15)库容和淹没区计算
    maven:apache.poi下载不了
    springboot:@RequestBody 注解只能处理json格式的请求字符串吗?
    arcpy计算统计值
    arcgis栅格计算器
    GeoTools:polygon 转 multipolygon&遍历multipolygon中的polygon
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270365.html
Copyright © 2020-2023  润新知