Manthan Codefest 19 (div1+div2)

有点难的一场。

题目链接: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\n",a);
28         else if (n%3==1) printf("%lld\n",b);
29         else printf("%lld\n",c);
30     }
31     return 0;
32 }
View Code

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\n",ans);
47     return 0;
48 }
View Code

这题还有一个很好的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 }
View Code

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 }
View Code

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 }
View Code
 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 }
SegTree

 

posted @ 2019-08-26 21:45  JHSeng  阅读(242)  评论(0编辑  收藏  举报