有点难的一场。
题目链接:https://codeforces.com/contest/1208
A:
水题。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 int t; 21 22 int main() { 23 scanf("%d",&t); 24 while (t--){ 25 ll a,b,c,n; scanf("%lld%lld%lld",&a,&b,&n); 26 c=a^b; 27 if (n%3==0) printf("%lld ",a); 28 else if (n%3==1) printf("%lld ",b); 29 else printf("%lld ",c); 30 } 31 return 0; 32 }
B:
这题很容易想到一种看似很对其实有bug的O(n)做法:维护双指针,往左往右扫,确定最小区间。
比较靠谱的做法是n方枚举区间,并维护不同元素个数,统计答案。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn=2e3+10; 21 int n,a[maxn],mul=0,ans=int_inf; 22 map<int,int>m; 23 24 int main() { 25 m.clear(); 26 scanf("%d",&n); 27 for (int i=1;i<=n;i++){ 28 scanf("%d",&a[i]); 29 m[a[i]]++; 30 } 31 for (auto i:m) 32 if (i.second>1) mul++; 33 if (!mul) return puts("0"),0; 34 for (int i=1;i<=n;i++){ 35 int ret=-1,tmp=mul; 36 for (int j=i;j<=n;j++){ 37 ret=j; 38 if (--m[a[j]]==1) tmp--; 39 if (!tmp){ 40 ans=min(ans,j-i+1); 41 break; 42 } 43 } 44 for (int j=i;j<=ret;j++) m[a[j]]++; 45 } 46 printf("%d ",ans); 47 return 0; 48 }
这题还有一个很好的O(nlogn)做法:二分尺取。
1 #include <bits/stdc++.h> 2 #define int int64_t 3 using namespace std; 4 int n; 5 6 bool judge(vector<int> &v, int mid) { 7 unordered_map<int, int> m; 8 unordered_set<int> s; // counter > 1 9 for (int i = 0; i < n; ++i) { 10 m[v[i]]++; // counter 11 if (m[v[i]] > 1) s.emplace(v[i]); 12 } 13 for (int i = 0; i < mid; ++i) { // pick all from [0,mid) 14 m[v[i]]--; 15 if (m[v[i]] < 2) s.erase(v[i]); 16 } 17 if (s.empty()) return true; // all were picked 18 int beg = 0, end = mid; 19 while (end < n) { 20 m[v[beg]]++; 21 if (m[v[beg]] > 1) s.emplace(v[beg]); 22 m[v[end]]--; 23 if (m[v[end]] < 2) s.erase(v[end]); 24 if (s.empty()) return true; 25 end++; 26 beg++; 27 } 28 return false; 29 } 30 31 signed main() { 32 ios::sync_with_stdio(false); 33 cin.tie(nullptr); 34 cin >> n; 35 vector<int> v(n); 36 for (int &i : v) cin >> i; 37 int lo = 0, hi = n; 38 while (lo < hi) { // 二分数量 39 int mid = (lo + hi) / 2; 40 if (judge(v, mid)) hi = mid - 1; 41 else lo = mid + 1; 42 } 43 if (lo > 0 and judge(v, lo - 1)) cout << lo - 1; 44 else if (judge(v, lo)) cout << lo; 45 else cout << max(0ll, lo + 1); 46 return 0; 47 }
C:
一个很有意思的xor幻方构造题。留意到给定的数n==4k,所以最后矩阵元素个数为16k^2,那么就可以把整个矩阵分为k^2个含有16个元素的子矩阵,第一个子矩阵从0~15依次分布,第二个子矩阵从16~31依次分布……这样做必然满足题意。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 1010; 21 int n, a[maxn][maxn]; 22 23 int main() { 24 scanf("%d", &n); 25 int cnt = 0; 26 for (int i = 0; i < 4; i++) 27 for (int j = 0; j < 4; j++) a[i][j] = cnt++; 28 for (int i = 0; i < n / 4; i++) 29 for (int j = 0; j < n / 4; j++) 30 if (i || j) { 31 for (int p = 0; p < 4; p++) 32 for (int q = 0; q < 4; q++) 33 a[i * 4 + p][j * 4 + q] = cnt++; 34 } 35 for (int i = 0; i < n; i++) { 36 for (int j = 0; j < n; j++) printf("%d ", a[i][j]); 37 puts(""); 38 } 39 return 0; 40 }
D:
不停地找区间最小值(如果有多个最小值,找最靠后的)即可。可以线段树,也可以树状数组+二分。
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 template <class T> 21 class BIT { 22 public: 23 vector<T> _bit; 24 int n; 25 26 BIT(int _n): n(_n) { 27 _bit.resize(n); 28 } 29 30 void add(int x, T v) { 31 while (x < n) { 32 _bit[x] += v; 33 x |= (x + 1); 34 } 35 } 36 37 T get(int x) { 38 T ret{}; 39 while (x >= 0) { 40 ret += _bit[x]; 41 x = (x & (x + 1)) - 1; 42 } 43 return ret; 44 } 45 }; 46 47 int main() { 48 int n; scanf("%d", &n); 49 vector<ll> s(n); 50 for (int i = 0; i < n; i++) scanf("%lld", &s[i]); 51 vector<int> a(n); 52 BIT<ll> bit(n); 53 for (int i = 0; i < n; i++) bit.add(i, i + 1); 54 for (int i = n - 1; i >= 0; i--) { 55 int low = 0, high = n - 1; 56 while (low < high) { 57 int mid = low + high >> 1; 58 if (bit.get(mid) > s[i]) 59 high = mid; 60 else low = mid + 1; 61 } 62 a[i] = low + 1; 63 bit.add(low, -low - 1); 64 } 65 for (int i = 0; i < n; i++) { 66 if (i) printf(" "); 67 printf("%d", a[i]); 68 } 69 puts(""); 70 return 0; 71 }
1 /* basic header */ 2 #include <bits/stdc++.h> 3 /* define */ 4 #define ll long long 5 #define dou double 6 #define pb emplace_back 7 #define mp make_pair 8 #define sot(a,b) sort(a+1,a+1+b) 9 #define rep1(i,a,b) for(int i=a;i<=b;++i) 10 #define rep0(i,a,b) for(int i=a;i<b;++i) 11 #define eps 1e-8 12 #define int_inf 0x3f3f3f3f 13 #define ll_inf 0x7f7f7f7f7f7f7f7f 14 #define lson (curpos<<1) 15 #define rson (curpos<<1|1) 16 /* namespace */ 17 using namespace std; 18 /* header end */ 19 20 const int maxn = 2e5 + 10; 21 struct Node { 22 ll minn, tag; 23 } segt[maxn << 2]; 24 int n, a[maxn]; 25 ll p[maxn]; 26 27 void maintain(int curpos) { 28 segt[curpos].minn = min(segt[lson].minn, segt[rson].minn); 29 } 30 31 void pushdown(int curpos) { 32 segt[lson].tag += segt[curpos].tag; segt[rson].tag += segt[curpos].tag; 33 segt[lson].minn += segt[curpos].tag; segt[rson].minn += segt[curpos].tag; 34 segt[curpos].tag = 0; 35 } 36 37 void build(int curpos, int curl, int curr) { 38 if (curl == curr) { 39 segt[curpos].minn = p[curl]; 40 return; 41 } 42 int mid = curl + curr >> 1; 43 build(lson, curl, mid); build(rson, mid + 1, curr); 44 maintain(curpos); 45 } 46 47 void update(int curpos, int curl, int curr, int ql, int qr, ll val) { 48 if (ql <= curl && curr <= qr) { 49 segt[curpos].tag += val; 50 segt[curpos].minn += val; 51 return; 52 } 53 int mid = curl + curr >> 1; 54 if (ql <= mid) update(lson, curl, mid, ql, qr, val); 55 if (mid < qr) update(rson, mid + 1, curr, ql, qr, val); 56 maintain(curpos); 57 } 58 59 ll queryMin(int curpos, int curl, int curr, int ql, int qr) { 60 if (ql <= curl && curr <= qr) 61 return segt[curpos].minn; 62 pushdown(curpos); 63 int mid = curl + curr >> 1; 64 ll ans = ll_inf; 65 if (ql <= mid) ans = min(ans, queryMin(lson, curl, mid, ql, qr)); 66 if (mid < qr) ans = min(ans, queryMin(rson, mid + 1, curr, ql, qr)); 67 return ans; 68 } 69 70 ll queryLastZero(int curpos, int curl, int curr) { 71 if (curl == curr) 72 return curl; 73 int mid = curl + curr >> 1; 74 if (queryMin(1, 1, n, mid + 1, curr) == 0) 75 return queryLastZero(rson, mid + 1, curr); 76 else return queryLastZero(lson, curl, mid); 77 maintain(curpos); 78 } 79 80 int main() { 81 scanf("%d", &n); 82 rep1(i, 1, n) scanf("%lld", &p[i]); 83 build(1, 1, n); 84 rep1(i, 1, n) { 85 int pos = queryLastZero(1, 1, n); 86 a[pos] = i; 87 update(1, 1, n, pos + 1, n, -i); 88 update(1, 1, n, pos, pos, ll_inf + i); 89 } 90 rep1(i, 1, n) printf("%d ", a[i]); 91 puts(""); 92 return 0; 93 }