Petrozavodsk Winter-2018. Jagiellonian U Contest.

[Petrozavodsk Winter-2018. Jagiellonian U Contest.]:


A

Petrozavodsk Winter-2018. Jagiellonian U Contest._第1张图片题意: 给你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));
    }
}

C

Petrozavodsk Winter-2018. Jagiellonian U Contest._第2张图片题意:给你两个长度为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);
	}
}

你可能感兴趣的:(2020寒假)