zoukankan      html  css  js  c++  java
  • 2017四川省赛E题( Longest Increasing Subsequence)

    提交地址: https://www.icpc-camp.org/contests/4rgOTH2MbOau7Z

    题意:

      给出一个整数数组,F[i]定义为以i结尾的最长上升子序列,然后问以此删除掉第i个数后F[1]^2 xor f[3]^2 xor .. xor F[n]^2 , 当然不会算删除的那个。 n <= 5000

    思路:

      比赛的时候看完了觉得是个傻逼题,觉得n^2logn能够跑过不知道为啥这么少人交,然后兴致冲冲的敲了一发返回T才意识到没那么简单,题目是把log给卡了的,然后n^2肯定是能过的,不过一直也没有思路,然后赛后听了题解,也不是很懂,也是最近才有时间想起来这个题目的。

      感觉没有思路是因为没有真正的理解LIS的原理,以前都是一直套的板子,所以不是很懂。然后补的时候仔细想了下,就是把v[i]当做以LIS长度为i结尾最小值,然后形成一个单调的队列,就可以使用二分查找到当前的值应该在v数组的哪个位置进而求得以a[i]结尾的LIS,然后更新当前的v[a[i]]数组。然后这个题目呢感觉就是挖掘这个本质,也是这道题让我懂了LIS的原理,因为删除了一个数,那么当前数的LIS值肯定是在原LIS值或者原LIS-1,所以我们就不需要二分去查找当前值应该属于哪个位置了,加入当前数的原LIS值为b我们只需要判断v[b]是否小于a[i],如果不是那v[b-1]肯定小于a[i],然后就降低了一个log

    代码:

    /** @xigua */
    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <string>
    #include <map>
    #include <climits>
    #include <ctime>
    #define PI acos(-1)
    using namespace std;
    typedef long long ll;
    typedef double db;
    const int maxn = 5e3 + 5;
    const int mod = 1e9 + 7;
    const int INF = 1e8 + 5;
    const ll inf = 1e15 + 5;
    const db eps = 1e-8;
    int d[maxn], a[maxn];
    
    void LIS(int n) {
        vector<int> v;
        for (int i = 1; i <= n; i++) {
            int si = v.size();
            int p = lower_bound(v.begin(), v.end(), a[i]) - v.begin(); //lower是严格 upper是不严格
            if (p == si) v.push_back(a[i]);
            else {
                v[p] = a[i];
            }
            d[i] = p + 1;
        }
    }
    
    void solve() {
        int n;
    
        while (cin >> n) {
            for (int i = 1; i <= n; i++)
                cin >> a[i];
            LIS(n);
            for (int i = 1; i <= n; i++) {
                int ans = 0;
                int v[maxn];
                for (int j = 1; j <= n; j++)
                    v[j] = n + 1;   //初始化为最大
                v[0] = 0;   //为了处理第一个数
                for (int j = 1; j <= n; j++) {
                    if (i == j) continue;
                    if (v[d[j]-1] < a[j]) {
                        ans ^= d[j] * d[j];
                        v[d[j]] = min(v[d[j]], a[j]);
                    }
                    else {
                        ans ^= (d[j] - 1) * (d[j] - 1);
                        v[d[j]-1] = min(v[d[j]-1], a[j]);
                    }
                }
                printf("%d%c", ans, i == n ? '
    ' : ' ');
            }
        }
    
    }
    
    int main() {
        int t = 1, cas = 1;
       // freopen("in.txt", "r", stdin);
       // freopen("out.txt", "w", stdout);
        //scanf("%d", &t);
        while(t--) {
           // printf("Case %d: ", cas++);
            solve();
        }
        return 0;
    }
    

      

  • 相关阅读:
    The best programmers are the quickest to Google
    NetBeans 时事通讯(刊号 # 117 Sep 16, 2010)
    Apache HttpClient 4.0.3 GA 发布
    warning LNK4070的解决办法
    看泡沫
    早秋精神
    NetBeans 时事通讯(刊号 # 117 Sep 16, 2010)
    Maven 3.0 RC1 发布
    关于类的数据成员的访问权限设计的一些思考
    看泡沫
  • 原文地址:https://www.cnblogs.com/ost-xg/p/7191032.html
Copyright © 2011-2022 走看看