sichuan2017 E. Longest Increasing Subsequence(LIS變形)

E. Longest Increasing Subsequence
Bobo learned how to compute Longest Increasing Subsequence (LIS) in O(n log n) in ICPCCamp.
For those who did not attend ICPCCamp as Bobo, recall LIS(a1, a2, … , an) is defined as f[1]2 ⊕ f[2]2 ⊕
· · · ⊕ f[n]
2 where ⊕ denotes the exclusive-or (XOR) and f is calculated as follows.
for i in [1, 2, …, n]
f[i] = 1
for j in [1, 2, …, i - 1]
if a[j] < a[i] then
f[i] = max(f[i], f[j] + 1)
Given sequence A = (a1, a2, … , an), Bobo would like to find LIS(B1), LIS(B2), … , LIS(Bn) where Bi
is the
sequence after removing the i-th element from A.
Input
The input contains zero or more test cases and is terminated by end-of-file. For each test case:
The first line contains an integer n. The second line contains n integers a1, a2, … , an.
• 2 ≤ n ≤ 5000
• 1 ≤ ai ≤ n
• The number of test cases does not exceed 10.
Output
For each case, output n integers which denote LIS(B1), LIS(B2), … , LIS(Bn).
Sample Input
5
2 5 3 1 4
Sample Output
5 13 0 8 0
題意:給你一個長度爲n的序列,問當刪除第i個數後,剩餘數的LIS的平方的異或和是多少。
題解:首先o(nlogn)預處理出以ai爲結尾的LIS的長度。
然後對於每次刪除的數ai來說,位於ai前面的LIS的長度不變,後面的要麼不變,要麼-1。現在判斷長度是否-1,假設ai後面存在一個數aj,如果aj前面存在一個數ak(!=ai),使得ak的LIS==aj的LIS-1並且ak < aj.則刪除ai後,對aj的LIS沒有影響。如果想對於任意的aj都儘量滿足沒有影響,則ak的值儘可能小。所以用s[]維護長度爲i 的最小結尾。
代碼:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
typedef long long int ll;
typedef pair<int,int>pa;
const int N=1e5+10;
const int MOD=1e9+7;
const ll INF=1e18;
const int inf=1e4;
int read()
{
    int x=0;
    char ch = getchar();
    while('0'>ch||ch>'9')ch=getchar();
    while('0'<=ch&&ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x;
}
/************************************************************/
int n;
int a[N];
int dp[N];//記錄以ai結尾的LIS的長度
int s[N];//記錄長度爲i的LIS的最小結尾
int f[N];//記錄長度爲i的LIS的結尾
void init()
{
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        fill(dp,dp+N-1,inf);
    int cnt=0;
    f[++cnt]=a[1];
    dp[1]=cnt;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>f[cnt])
        {
            f[++cnt]=a[i];
            dp[i]=cnt;
        }
        else
        {
            int pos=lower_bound(f+1,f+cnt,a[i])-f;
            f[pos]=a[i];
            dp[i]=pos;
        }
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        init();
        for(int i=1;i<=n;i++)
        {
            memset(s,0x3f3f3f3f,sizeof(s));
            s[0]=0;
            ll ans=0;
            for(int j=1;j<i;j++)
            {
                s[dp[j]]=min(s[dp[j]],a[j]);
                ans^=(ll)dp[j]*(ll)dp[j];
            }
            for(int j=i+1;j<=n;j++)
            {
                if(a[j]>s[dp[j]-1])
                {
                    s[dp[j]]=min(s[dp[j]],a[j]);
                    ans^=(ll)dp[j]*(ll)dp[j];
                }
                else
                {
                    s[dp[j]-1]=min(s[dp[j]-1],a[j]);
                    ans^=(ll)(dp[j]-1)*(ll)(dp[j]-1);
                }
            }
            if(i!=1) printf(" ");
            printf("%lld",ans);
        }
        printf("\n");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章