Codeforces 1208B/C 最長不重複子串/構造行列異或和相同矩陣

1208B

題意:給你一個序列,讓你刪掉一個子串,問你怎樣刪,留下的部分是最長的不重複子序列。
思路:看的曉陽隊的思想。問的是求刪掉的子串,那麼我們轉化成 求剩下的最長不重複子串。
因爲剩下的可能是右邊一段或者左邊一段或者兩邊合起來!所以:
離散化後複製一份放後面,然後尺取法求序列中間的最長不重複。
但是能做答案的只能是l從1開始或者橫跨n和n+1的!
想想爲什麼。
因爲只能刪掉中間的
如果取中間的一段最長不重複子串 就得從兩邊拿 顯然是不可能的
so要有l==1或者r>=n的限制(r可取n 是右部區間。r大於n 是右邊與左邊連續區間
才能作爲最大值。
下面是AC代碼。尺取法
離散化是nlogn的複雜度
尺取法是On的複雜度,可以接受。
還有就是不要只在增加爲1的時候纔去判,若增加爲2再取收縮時 也有可能是最大!

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#define ll long long
#define inf 0x3f3f3f3f
#define sd(a) scanf("%d",&a)
#define sdd(a,b) scanf("%d%d",&a,&b)
#define cl(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define dbg() printf("aaa\n")
using namespace std;
//注意開二倍數組!!!!
int a[4010],acopy[2010];
int num[2010];
int main() {
    int n;
    cl(num,0);
    sd(n);
    rep(i,1,n){
        sd(a[i]);
        acopy[i]=a[i];
    }
    sort(acopy+1,acopy+n+1);
    int size=unique(acopy+1,acopy+n+1)-(acopy+1);//注意這裏!!!
    rep(i,1,n){
        a[i]=lower_bound(acopy+1,acopy+size+1,a[i])-acopy;
    }
    rep(i,1,n){//複製一遍
        a[n+i]=a[i];
    }//然後找最長不重複子序列
    int l=1,r=1;
    int len=0;//最長不重複子序列
    while(l<=n){//無需刻意控制長度爲n 因爲長度一定爲n
        num[a[r]]++;
        while(num[a[r]]>1){
            num[a[l]]--;
            l++;
        }
        if(l==1||r>=n) {
            if(len<r-l+1) len=r-l+1;
        }
        r++;
    }
    printf("%d\n",n-len);
	return 0;
}
/*
10
1 100 100 1000 1000 100 10 1 1000 1
*/

1208C

題意:給你一個數n(n是4的倍數)
讓你構造一個n* n的矩陣,滿足行列異或和相等
思路:剛剛拿到這個題 是真的不會。。。
後來看了題解發現
首先因爲某個數和自己異或 一定是0!
所以說我們只要安排,兩個相同的數在同一行列就行了
注意 ,而這裏不能相同。
但是我們可以讓它們高位相同
什麼意思?
來看:因爲方陣n一定爲4的倍數
所以說我們先把方陣分成四個部分
每個部分的都是n/2的方陣 而n/2一定是2的倍數!(這點很重要)
我們要做的是,四個小方陣,每個的同一位置,放相同的數*4,再各自加上0 1 2 3
什麼道理?
乘以四就是各自左移兩位,這樣做保證了每行/列 高位有兩個相同的數,低位有偶數個0/1/2/3!
這樣每行每列異或和都爲0!
思路寫的很亂,總之就是,大方陣分成四個小方陣,每個小方陣每個相同位置的數 高位相同 低位分別是0 1 2 3 然後又因爲每個小方陣都是偶數階 所以保證了低位可以是偶數個相同的數異或 高位也有n/2個相同的數異或 最終異或結果都是0
下面是ac代碼

int mp[1010][1010];
int main() {
	int n;
	sd(n);
	//應該是確定四分之一然後確定其他 而不是確定4x4再確定其他- -這個也行?
	int cnt=0;
	rep(i,1,n/2){//有了思路其實還挺好想的
		rep(j,1,n/2){//也就剛好是4的倍數 不然8 9都不行
			mp[i][j]=cnt*4;
			mp[i][j+n/2]=cnt*4+1;
			mp[i+n/2][j]=cnt*4+2;
			mp[i+n/2][j+n/2]=cnt*4+3;
			cnt++;
		}
	}
	rep(i,1,n){
		rep(j,1,n){
			printf("%d%c",mp[i][j],j==n?'\n':' ');
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章