Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)

别来无恙 提交于 2020-12-23 04:31:36

二进制专场,还被FST一题。

A、签到,题意是,给定a,b,c

f(0)=a,f(1)=b,f(n)=f(n-1)^f(n-2)

求f(n)

稍微化简就看得出f(x)是按照a,b,a^b这样在循环出现

因为a^b^a=b,a^b^b=a

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=500005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

int t,a,b,n;

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>t;
    while(t--){
        cin>>a>>b>>n;
        if(n==0) cout<<a<<endl;
        else if(n==1) cout<<b<<endl;
        else{
            int k=n%3;
            if(k==0) cout<<a<<endl;
            else if(k==1) cout<<b<<endl;
            else cout<<(a^b)<<endl;
        }
    }
    return 0;
}

B、被FST的一道题,题意是选定一个[l,r]的连续区间将它删去,使得剩下的数字两两不相同,不需要删去输出0即可

连续子段的问题我上了尺取法,假设[l,r]的区间是我要删去的区间,在确定l的情况下不断把r减小,来找到最小的区间。

一开始过不了pp,想了一下发现是删除开始和结尾一段连续区间的情况没有考虑到,加了一下判断过了pp。

后来找半天小一点的hack,终于让我给翻到了:

8
1 2 3 4 2 6 5 4

显然应该删除第四位和第五位上的2,4,但是我却输出了3,debug时候发现[l,r]区间根本就没有遍历到第四位和第五位上去。

看正解发现是O(n^2logn)的,大意是删除一段子区间之后只会留下一个前缀和一个后缀,它们的长度可以为0

那么枚举没有重复长度的前缀,找到最长的没有任何重复数字的后缀,用map维护住即可,注意前后缀都为空的下标细节

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=500005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}
 
int n,a[maxn];
mpii mp;
 
signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n;
    re(i,1,n) cin>>a[i];
    int ans=n-1;
    re(i,1,n){
        bool can=1;
        mp.clear();
        re(j,1,i-1){
            mp[a[j]]++;
            if(mp[a[j]]==2){
                can=0;
                break;
            }
        }
        int p=n+1;
        rre(j,n,i){
            mp[a[j]]++;
            if(mp[a[j]]==1) p=j;
            else break;
        }
        if(can) ans=min(ans,p-i);
    }
    cout<<ans;
    return 0;
}
/*
6
2 2 3 3 4 2
8
1 2 3 4 2 6 5 4
10
7 6 5 4 3 2 1 7 7 7
*/

C、给定一个n,保证n是4的倍数,构造一个n*n的矩阵,使得[0,n^2-1]当中的每个数字仅出现一次,并且矩阵每一行每一列异或和为相同

先猜个结论,行列异或和都为0

比赛的时候ly给的解法是四个四个分组,我没太看懂,比赛之后跟zyf商量半天总算搞懂了。

首先随便找一个4*4满足条件的矩阵来,我用的下面这个:

这个其实用了下面的一个结论,在PS当中。

0   1   2   3

4   5   6   7

8   9   10   11

12   13   14   15

考虑这样一个东西:

a^b=(a+c)^(b+c)的条件是什么?

答案是c>a&&c>b

实际上如果c>a,那么a+c只会在原来a为0的二进制位上作出更改,而在偶数次异或之后异或和会变为0

例如:a^a=0,a^a^a^a=0

所以把4*4的矩阵不断重复,每次加上16、32、48即可

下面的get函数是用来获得某个点的编号的,类似于n行n列的矩阵,a[i][j]前面一共有i*n+j个元素(i,j从0开始)

真就数据结构期末考试呗。

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=500005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

int n;
int ans[1005][1005];
int a[4][4]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

void out(){
    fo(i,0,n){
        fo(j,0,n){
            cout<<ans[i][j]<<' ';
        }
        cout<<endl;
    }
}

int get(int i,int j){
    return (n/4)*(i/4)+(j/4);
}

void solve(){
    fo(i,0,n){
        fo(j,0,n){
            ans[i][j]=get(i,j)*16+a[i%4][j%4];
        }
    }
}

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n;
    solve();
    out();
    return 0;
}

PS:从这儿嗨学了一个结论,4的倍数开始的连续的4个数异或和为0

比如0、1、2、3和8、9、10、11

 

D、假设这儿有一个n的排列,每个位置上的数字是pi,si表示在i之前比pi小的所有数字之和

现在给定n和si,要你重建pi,保证有解

首先考虑1的位置,假设有这样一个排列:

3   2   5   1   4

它的si数组很容易求出:

0   0   5   0   6

首先,对于1来说,它对应位置上的si一定是0,因为不会有数字比1更小,并且对于所有在1后面的数字,他们的si一定不为0,这意味着最后一个0的位置一定是1

在上例中,首先找到1的位置,并且开始重建pi:

*   *   *   1   *

随后把1位置上的si设为无穷,并且把1位置后面所有的si减1,这一步可以用线段树维护住,si如图:

0   0   5   inf   5

此时找2的位置,很显然,在1消失之后,2成为了最小的数字,此时最后一个0的位置就是2的位置,重复上述操作。

pi:*  2   *  1   *

si:0  inf   3   inf-2   3

算法到这儿已经很明确了,用线段树维护住si的值,从1到n往回填充数字。

下面的问题是如何logn找到最后一个0的位置,利用线段树二分向下查找即可,每一次先看右侧的最小值是否是0,如果不是,向左查找,这样一定可以找到最靠右的0的位置。

写的时候下传标记写锅了,我居然只在标记等于0的时候才下传,以后还是少用!a来判断a是否等于0,多用==

代码:

#include <bits/stdc++.h>
#define int long long
#define sc(a) scanf("%lld",&a)
#define scc(a,b) scanf("%lld %lld",&a,&b)
#define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c)
#define schar(a) scanf("%c",&a)
#define pr(a) printf("%lld",a)
#define fo(i,a,b) for(int i=a;i<b;++i)
#define re(i,a,b) for(int i=a;i<=b;++i)
#define rfo(i,a,b) for(int i=a;i>b;--i)
#define rre(i,a,b) for(int i=a;i>=b;--i)
#define prn() printf("\n")
#define prs() printf(" ")
#define mkp make_pair
#define pii pair<int,int>
#define pub(a) push_back(a)
#define pob() pop_back()
#define puf(a) push_front(a)
#define pof() pop_front()
#define fst first
#define snd second
#define frt front()
#define bak back()
#define mem0(a) memset(a,0,sizeof(a))
#define memmx(a) memset(a,0x3f3f,sizeof(a))
#define memmn(a) memset(a,-0x3f3f,sizeof(a))
#define debug
#define db double
#define yyes cout<<"YES"<<endl;
#define nno cout<<"NO"<<endl;
using namespace std;
typedef vector<int> vei;
typedef vector<pii> vep;
typedef map<int,int> mpii;
typedef map<char,int> mpci;
typedef map<string,int> mpsi;
typedef deque<int> deqi;
typedef deque<char> deqc;
typedef priority_queue<int> mxpq;
typedef priority_queue<int,vector<int>,greater<int> > mnpq;
typedef priority_queue<pii> mxpqii;
typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii;
const int maxn=1000005;
const int inf=0x3f3f3f3f3f3f3f3f;
const int MOD=100000007;
const db eps=1e-10;
int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;}
int lowbit(int x){return x&-x;}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int mmax(int a,int b,int c){return max(a,max(b,c));}
int mmin(int a,int b,int c){return min(a,min(b,c));}
void mod(int &a){a+=MOD;a%=MOD;}
bool chk(int now){}
int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;}
int ll(int p){return p<<1;}
int rr(int p){return p<<1|1;}
int mm(int l,int r){return (l+r)/2;}
int lg(int x){if(x==0) return 1;return (int)log2(x)+1;}
bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;}
db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));}
bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;}

int n,s[maxn],ans[maxn];
int tr[maxn],tag[maxn];

void up(int p){tr[p]=min(tr[ll(p)],tr[rr(p)]);}
void down(int p){
    if(tag[p]){
        tr[ll(p)]+=tag[p];
        tr[rr(p)]+=tag[p];
        tag[ll(p)]+=tag[p];
        tag[rr(p)]+=tag[p];
        tag[p]=0;
    }
}

void build(int p,int l,int r){
    if(l==r){
        tr[p]=s[l];
        return;
    }
    int m=mm(l,r);
    build(ll(p),l,m);
    build(rr(p),m+1,r);
    up(p);
}

int q(int p,int l,int r,int pos){
    if(l==r&&l==pos)
        return tr[p];
    int m=mm(l,r);
    down(p);
    int ans;
    if(pos<=m) ans=q(ll(p),l,m,pos);
    else ans=q(rr(p),m+1,r,pos);
    up(p);
    return ans;
}

void change(int p,int l,int r,int L,int R,int v){
    if(L<=l&&r<=R){
        tr[p]+=v;
        tag[p]+=v;
        return;
    }
    int m=mm(l,r);
    down(p);
    if(L<=m) change(ll(p),l,m,L,R,v);
    if(R>m) change(rr(p),m+1,r,L,R,v);
    up(p);
}

int pos(int p,int l,int r){
    if(l==r) return l;
    int res=-1;
    int m=mm(l,r);
    down(p);
    if(tr[rr(p)]==0)
        res=pos(rr(p),m+1,r);
    else
        res=pos(ll(p),l,m);
    up(p);
    return res;
}

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n;
    re(i,1,n) cin>>s[i];
    memmx(tr);
    build(1,1,n);
    re(i,1,n){
        int p=pos(1,1,n);
//        re(j,1,n) cout<<q(1,1,n,j)<<" \n"[j==n];
        ans[p]=i;
        if(p!=n) change(1,1,n,p+1,n,-i);
        change(1,1,n,p,p,inf);
    }
    re(i,1,n) cout<<ans[i]<<' ';
    return 0;
}
/*
5
0 1 1 1 10
*/

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!