[Petrozavodsk Winter-2018. Jagiellonian U Contest.]:
题意: 给你n个数 让你分成A B 两部分(其中一部分可为空) 使得 xor(A)与xor(B) 的差值最小。
思路:1.异或为0的为 说明n个数中具有偶数个这一位是1 无论怎么分配给A B
这一位A和B肯定一样 要么都是0 要么都是1 所以这一位对题目要得到答案的没有影响。
所以我们把所有的a[i]的 sum为0的这些位也都变成0. a[i]&=sum 只会让sum为0的这些位有可能改变。
假设A>B
首先肯定可以想到的是我们肯定要从高位到低位贪心。很明显的是 这63位里面最靠前的有含奇数个1的位(其实最靠前有1的位就行 因为偶数个的位已经都成0了)。这些奇数肯定 奇数个1给A 偶数个1给B 这样才能A>B。
然后因为分成A B两部分不限个数我们可以考虑线性基。很好。
就是想让A除了最高位是1(B的最高位是0) 接下来的位能是0尽量是0. 虽然A去了线性基里面的最高的p[i] (可以有好多数组成 我们也不确定为什么要取这么不确定性的) 但是以后的异或过程贪心可以把前面的部分消掉 这本来就是线性基的作用 A是0的位B是1 A越这样小 B就越这样大
#include
#include
#include
#define m(a,b) memset(a,b,sizeof a)
#define fnq freopen("input.txt","r",stdin)
using namespace std;
typedef long long ll;
const int N=1e5+5,Maxbit=63;
ll a[N],p[Maxbit+1];
int main(){
//fnq;
int T;scanf("%d",&T);
while(T--){
m(p,0);ll sum=0;
int n;scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%lld",&a[i]),sum^=a[i];
for(int i=1;i<=n;++i) a[i]&=sum;
for(int i=1;i<=n;++i){
ll x=a[i];
for(int j=Maxbit;j>=0;--j){
if(!(x>>j)&1) continue;
if(!p[j]) {
p[j]=x;break;}
x^=p[j];
}
}
for(int i=1;i<=n;++i) a[i]&=sum;
ll A,B;int i;
for(i=Maxbit;i>=0;--i)
if(p[i]) {
A=p[i];break;}
for(--i;i>=0;--i)
if(p[i]&&((A>>i)&1)) A^=p[i];
printf("%lld\n",A-(sum^A));
}
}
题意:给你两个长度为n的序列 让你输出最大的m 使得ai aj …ak 是严格递增 bi bj …bk 也是严格递增 m则是他们的个数。
思路: 第一个序列看成第二维 第二个序列看成第三维 下标是第一维(已有序)。就是三维裸的LIS(注意严格 只有A.x>B.x A.y>B.y A.z>B.z 才是A>B 三维中不能有一个等于)。
#include
using namespace std;
const int N=2e5+5;
struct node{
int x,y,z;}a[N];
inline int cmpy(int i,int j){
return a[i].y<a[j].y;}
int dp[N],q1[N],q2[N];
int refl[N],tot;
struct BIT{
#define low(x) ((x)&(-x))
int A[N];
void update(int x,int val){
while(x<=tot) A[x]=max(A[x],val),x+=low(x);
}
int query(int x){
int ans=0;
while(x) ans=max(ans,A[x]),x-=low(x);
return ans;
}
void clear(int x){
while(x<=tot){
if(!A[x]) return;
A[x]=0,x+=low(x);
}
}
}B;
void cdq(int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
cdq(l,mid);
int num1=0,num2=0;
for(int i=l;i<=mid;++i) q1[++num1]=i;
for(int i=mid+1;i<=r;++i) q2[++num2]=i;
sort(q1+1,q1+num1+1,cmpy),sort(q2+1,q2+num2+1,cmpy);
for(int i=1,j=1;j<=num2;++j){
while(i<=num1&&a[q1[i]].y<a[q2[j]].y) B.update(a[q1[i]].z,dp[q1[i]]),++i;
dp[q2[j]]=max(dp[q2[j]],B.query(a[q2[j]].z-1)+1);
}
for(int i=1;i<=num1;++i) B.clear(a[q1[i]].z);
cdq(mid+1,r);
}
int main(){
int T;scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i].y),a[i].x=1,dp[i]=1;
for(int i=1;i<=n;++i) scanf("%d",&a[i].z),refl[i]=a[i].z;
sort(refl+1,refl+n+1);tot=unique(refl+1,refl+n+1)-(refl+1);
for(int i=1;i<=n;++i) a[i].z=lower_bound(refl+1,refl+tot+1,a[i].z)-refl;
cdq(1,n);
int ans=0;
for(int i=1;i<=n;++i) ans=max(ans,dp[i]);
printf("%d\n",ans);
}
}