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;
}