正题
CF750F1
CF750F2
题目大意
给你一个数列,问有多少个数可以由一个单调递增的子序列异或得到
解题思路
对于F1,可以用p存下得到一个数的最小值(即当前子序列前缀的最后一个数),然后直接暴力转移
对于F2,直接暴力转移会TLE
可以发现,该数列一定存在重复的数,而部分转移会重复(比如前面可以转移的后面也转移了,但一定不会更优)
考虑更改转移方式,先对数列进行排序,设pip_ipi为得到iii的最前位置,那么对于每次转移,就在当前数中找第一个大于pip_ipi的最小的数
时间复杂度O(s2logn)O(s^2\ log\ n)O(s2 log n)
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 1000100
#define fs first
#define sn second
using namespace std;
int n,x,g,w,num,now,p[N],s[N],b[N];
pair<int,int>a[N];
int main()
{for(int i=1;i<=8191;++i)p[i]=10000000;scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%d",&a[i].fs);a[i].sn=i;}sort(a+1,a+1+n);now=1;while(now<=n){w=1;g=a[now].fs;b[w]=a[now].sn;now++;while(now<=n&&a[now].fs==g)b[++w]=a[now].sn,now++;p[g]=min(p[g],b[1]);for(int i=1;i<=8191;++i)if(p[i]<b[w])p[i^g]=min(p[i^g],b[lower_bound(b+1,b+1+w,p[i])-b]);}for(int i=1;i<=8191;++i)if(p[i]<=1000000)num++;printf("%d\n0",num+1);for(int i=1;i<=8191;++i)if(p[i]<=1000000)printf(" %d",i);return 0;
}