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");
}
}