• HDU 5172 GTY's gay friends 线段树+前缀和+全排列


    题目链接:

    hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5172

    bc(中文): http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=567&pid=1003

    题解:

    线段树+前缀和

    一个区间要满足1到n的一个排列,要同时满足两点,一是它的和是n*(n+1)/2,这个可以用前缀和直接求;二是它每个元素不能重复。

    区间内每个元素都不能重复:

      记录第i个元素的左边一个离他最近的值与他相等的数的位置,记在arr[i]里面,对于区间[L,r]要满足区间里面最大的arr[i](L<=i<=r)要小于L;这个可以用线段树或rmq维护。

    要先比较第一个条件,即和要先等于n*(n+1)/2,满足了再去查线段树,否则会超时。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define lson (o<<1)
     6 #define rson ((o<<1)+1)
     7 #define M (l+(r-l)/2)
     8 using namespace std;
     9 typedef long long LL;
    10 
    11 const int maxn = 1e6 + 10;
    12 LL sumv[maxn << 2];
    13 int maxv[maxn << 2];
    14 int arr[maxn],vis[maxn];
    15 int n, m;
    16 
    17 int max(int a, int b) { return a > b ? a : b; }
    18 
    19 void build(int o, int l, int r) {
    20     if (l == r) {
    21         maxv[o] = arr[l];
    22     }
    23     else {
    24         build(lson, l, M);
    25         build(rson, M + 1, r);
    26         maxv[o] = max(maxv[lson], maxv[rson]);
    27     }
    28 }
    29 
    30 int ql, qr;
    31 void query(int o, int l, int r,int &ma) {
    32     if (ql <= l&&r <= qr) {
    33         ma = max(ma, maxv[o]);
    34     }
    35     else {
    36         if (ql <= M) query(lson, l, M,ma);
    37         if (qr > M) query(rson, M + 1, r, ma);
    38     }
    39 }
    40 
    41 bool check(int l,int r) {
    42     LL nn = r - l + 1;
    43     if (nn*(nn + 1) / 2 != sumv[r] - sumv[l - 1]) return false;
    44     int ma = -1;
    45     query(1, 1, n,ma); 
    46     if (ma >= l) return false;
    47     return true;
    48 }
    49 
    50 void init() {
    51     sumv[0] = 0;
    52     memset(vis, 0, sizeof(vis));
    53 }
    54 
    55 int main() {
    56     while(scanf("%d%d", &n, &m) == 2 && n) {
    57         init();
    58         for (int i = 1; i <= n; i++) {
    59             int x;
    60             scanf("%d", &x);
    61             sumv[i] = sumv[i - 1] + x;
    62             arr[i] = vis[x];
    63             vis[x] = i;
    64         }
    65         build(1,1,n);
    66         while (m--) {
    67             scanf("%d%d", &ql, &qr);
    68             LL len = qr - ql + 1;
    69             if (check(ql,qr)) {
    70                 puts("YES");
    71             }
    72             else {
    73                 puts("NO");
    74             }
    75         }
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    HTML笔记
    html文本格式化
    标题大小与字体大小的关系
    html学习笔记
    冒泡排序
    直接插入算法
    绘制针状图
    绘制矢量图
    饼图pie 或者pie3
    三维直方图
  • 原文地址:https://www.cnblogs.com/fenice/p/5441132.html
Copyright © 2020-2023  润新知