A. GukiZ and Contest
题意: 按rating排名 相同rating同名次 但是这个名次要计算人数
思路: sort乱搞就可以了 - -
参考code:
// // Created by TaoSama on 2015-06-13 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 1e5 + 10; int n; struct P { int m, id, p; bool operator < (const P& rhs) const { return m > rhs.m; } } a[2005]; bool cmp(P x, P y) { return x.id < y.id; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(cin >> n) { for(int i = 1; i <= n; ++i) { cin >> a[i].m; a[i].id = i; } sort(a + 1, a + 1 + n); int last = 1; a[1].p = 1; for(int i = 2; i <= n; ++i) { if(a[i].m == a[i - 1].m) { a[i].p = last; } else { a[i].p = i; last = i; } } sort(a + 1, a + 1 + n, cmp); for(int i = 1; i <= n; ++i) cout << a[i].p << ' '; cout << endl; } return 0; }
题意: 重排a串使得不重合的a串和b串的出现和尽量大
思路: 枚举其中b或者c串个数算出b的个数 大的就更新就可以了 或者贪心一下 每次看a还是b放的多 每次放放的多的那个
参考code:
第二种思路
// // Created by TaoSama on 2015-06-13 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 1e5 + 10; string a, b, c; int aa[26], bb[26], cc[26]; int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(cin >> a >> b >> c) { memset(aa, 0, sizeof aa); memset(bb, 0, sizeof bb); memset(cc, 0, sizeof cc); for(int i = 0; i < a.size(); ++i) aa[a[i] - 'a'] ++; for(int i = 0; i < b.size(); ++i) bb[b[i] - 'a'] ++; for(int i = 0; i < c.size(); ++i) cc[c[i] - 'a'] ++; int cntb = INF, cntc = INF; while(true) { for(int i = 0; i < 26; ++i) if(bb[i]) cntb = min(cntb, aa[i] / bb[i]); for(int i = 0; i < 26; ++i) if(cc[i]) cntc = min(cntc, aa[i] / cc[i]); if(cntb == 0 && cntc == 0) break; if(cntb > cntc) { cout << b; for(int i = 0; i < 26; ++i) aa[i] -= bb[i]; } else if(cntc) { cout << c; for(int i = 0; i < 26; ++i) aa[i] -= cc[i]; } } for(int i = 0; i < 26; ++i) while(aa[i]--) cout << char(i + 'a'); cout << '\n'; } return 0; }
题意: n摞箱子 一开始所有人0出 每摞1-n下标 至少有一摞箱子个数不为0
m个人同时开始搬箱子 i->i+1摞移动 和 搬走一个箱子 都使用单位时间
思路: - - 这个题要倒着想 然后就可以贪心了 要搬完 所以肯定有人去最后一摞箱子
从最后一个往前搬 然后时间少可以搬完 时间更多肯定也可以搬完 二分判断是否可行就可以了
参考code:
// // Created by TaoSama on 2015-06-15 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 1e5 + 10; int n, m, a[N]; bool check(long long x) { long long can, left, last; int j = n; while(!a[j]) j--; left = a[j]; if(x - j <= 0) return false; // cout << "j: " << j << " left: " << left << endl; for(int i = 1; i <= m; ++i) { can = x - j; // cout << "i: " <<i << " j: " << j << " left: " << left << endl; if(can >= left) can -= left, --j; else { left -= can; continue; } while(j && can >= a[j]) can -= a[j], --j; // cout << can <<endl; left = a[j] - can; if(j == 0) return true; } return false; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(cin >> n >> m) { long long sum = n; for(int i = 1; i <= n; ++i) cin >> a[i], sum += a[i]; long long l = 0, r = sum; // cout << sum << endl; while(l <= r) { long long mid = l + r >> 1; if(check(mid)) r = mid - 1; else l = mid + 1; // cout << l << ' ' << mid << ' ' << r << endl; } cout << l << '\n'; } return 0; } //8 52
D. GukiZ and Binary Operations
题意: 一个数列 2个操作 1-> [l,r]区间数同时+x 2->查询[1,n]区间第一个x和最后一个x的下边差值 没有输出-1
思路: 貌似线段树不可搞 - - 维护不了第二种操作值 那么分块大法好 意思和线段树差不多 add[i]维护每块的共同加数
然后在开一个存一下原来的块 磊神这个姿势挺优美的 - - 发现每块取1000是个很赞的数字 具体看code吧
参考code:
// // Created by TaoSama on 2015-06-16 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 5e5 + 10; const int B = 1e3; vector<long long> a[1000], b[1000]; long long add[1000]; int n, q; void update(int l, int r, int x) { for(int i = l; i <= r;) { if(i % B == 0 && i + B - 1 <= r) { add[i / B] += x; i += B; } else { a[i / B][i % B] += x; i++; } } if(l % B) { b[l / B] = a[l / B]; sort(b[l / B].begin(), b[l / B].end()); } if((r + 1) % B) { b[r / B] = a[r / B]; sort(b[r / B].begin(), b[r / B].end()); } } long long query(int x) { int l = -1, r = -1; for(int i = 0; i <= n / B; ++i) { // cout << i << ' ' << x - add[i] << endl; auto t = lower_bound(b[i].begin(), b[i].end(), x - add[i]); if(t != b[i].end() && *t == x - add[i]) { for(int j = 0; j < a[i].size(); ++j) { if(a[i][j] == *t) { l = B * i + j + 1; break; } } break; } } for(int i = n / B; i >= 0; --i) { auto t = lower_bound(b[i].begin(), b[i].end(), x - add[i]); if(t != b[i].end() && *t == x - add[i]) { for(int j = a[i].size() - 1; j >= 0; --j) { if(a[i][j] == *t) { r = B * i + j + 1; break; } } break; } } // cout << l << ' ' << r << endl; return ~l && ~r ? r - l : -1; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(scanf("%d%d", &n, &q) == 2) { for(int i = 0; i <= n / B; ++i) { a[i].clear(), b[i].clear(); add[i] = 0; } for(int i = 0; i < n; ++i) { int x; scanf("%d", &x); a[i / B].push_back(x); b[i / B].push_back(x); } for(int i = 0; i <= n / B; ++i) sort(b[i].begin(), b[i].end()); while(q--) { int op, x, y, z; scanf("%d", &op); if(op == 1) { scanf("%d%d%d", &x, &y, &z); update(x - 1, y - 1, z); // for(auto &x : a[0]) cout << x << ' '; cout << endl; // for(auto &x : b[0]) cout << x << ' '; cout << endl; cout << endl; } else { scanf("%d", &x); printf("%I64d\n", query(x)); } } } return 0; }