题意:
这个题就是先将每个地方的最长上升子序列的长度预处理出来,同时将这个地方最长的长度由前面多少个f[j]+1转换过来的统计下来(我是在j里面存下i,这样我们在之后删除的时候,我删除j了,他只会影响到它被利用的里面的)同时每次开始的时候它的结果都是原数组的异或的值异或上当前的f[i]*f[i];这个就表明把a[i]删除了,之后我们在从当前的位置出发,将当前的点的里面个数+1,直到我们现在的点最大值转换的点全部不在了,那么我们就将这个点原本的异或值抵消,同时它的f[i]现在减少了1,再把现在的(f[i]-1)*(f[i]-1)异或上,另外这个点也没有了,也要删,直到我所影响的遍历完,最后输出值就行了
const int N = 5e3 + 10, M = 5e2 + 10;
int n,m,op;
int a[N],b[N],f[N];
vector<int>v[N];
int mp[N];
void dfs(int u)
{
int tt=v[u].size();
for(int j=0;j<tt;j++)
{
int x=v[u][j];//要除掉的
mp[x]++;
if(mp[x]==b[x])//删完了,它里面的也要删完,并且当前的长度要减少1;
{
op=op^(f[x]*f[x]);//将原本异或的抵消掉
op=op^((f[x]-1)*(f[x]-1));
dfs(x);
}
}
}
void df()
{
while(cin>>n)
{
int num=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=0;
v[i].clear();
f[i]=1;
for(int j=1;j<=i-1;j++)
{
if(a[j]<a[i])
{
if(f[i]<=(f[j]+1))
f[i]=f[j]+1;
}
}
for(int j=1;j<=i-1;j++)
{
if(a[j]<a[i])
{
if(f[i]==(f[j]+1))
{
v[j].push_back(i);
b[i]++;
}
}
}
num^=f[i]*f[i];
}
for(int i=1;i<=n;i++)
{
memset(mp,0,sizeof(mp));
op=num^(f[i]*f[i]);//前面的
dfs(i);
cout<<op<<" ";
}
cout<<endl;
}
}