标签:res shuff assign dom 遇到 put 奇数 说明 ems
D - Go Latin
签到题,按题意模拟就可以了,容易看漏情况,小心一点。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char s[1000005];
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n;
cin>>n;
while(n--){
cin>>s;
int l=strlen(s);
if(s[l-1]=='a'||s[l-1]=='o'||s[l-1]=='u'){
s[l]='s';
s[l+1]='\0';
}
else if(s[l-1]=='i'||s[l-1]=='y'){
s[l-1]='i';
s[l]='o';
s[l+1]='s';
s[l+2]='\0';
}
else if(s[l-1]=='l'||s[l-1]=='r'||s[l-1]=='v'){
s[l]='e';
s[l+1]='s';
s[l+2]='\0';
}
else if(s[l-1]=='n'){
s[l-1]='a';
s[l]='n';
s[l+1]='e';
s[l+2]='s';
s[l+3]='\0';
}
else if(s[l-2]=='n'&&s[l-1]=='e'){
s[l-2]='a';
s[l-1]='n';
s[l]='e';
s[l+1]='s';
s[l+2]='\0';
}
else if(s[l-1]=='t'||s[l-1]=='w'){
s[l]='a';
s[l+1]='s';
s[l+2]='\0';
}
else {
s[l]='u';
s[l+1]='s';
s[l+2]='\0';
}
cout<<s<<endl;
}
}
L - Working Plan
贪心,感觉这个难度应该在国内可以难倒一片才对,事实说明日韩台他们可能是水平高一点。
有m个工人,每个工人要工作wi天,每次连续工作w天,然后休息至少h天之后才能开始新一轮工作,每天需要di个人,求一种分配方案。
一开始以为是网络流,演了半天,事实上因为w和h是所有工人公用的所以可能导致有简单的解法。
首先wi必须被w整除,di的和也是。
然后第一天必须要找刚好这么多人覆盖掉,所以直接尝试暴力更新就可以了(小心后面的变成负数,在这里WA了一次)。每次找要工作的剩余天数最多的那个,因为决策包容性,让最多的那个先工作先休息,有两张2肯定比一张4好,这就是决策包容性。所以这里要整个堆。然后用个队列让他们到时间以后回来堆里面。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue<pair<int, int> > pq;
queue <pair<int, pair<int, int> > > q;
int d[2005];
vector<int> ans[2005];
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int m, n, w, h;
while(~scanf("%d%d%d%d", &m, &n, &w, &h)) {
while(!pq.empty())
pq.pop();
while(!q.empty())
q.pop();
bool suc = 1;
for(int i = 1; i <= m; ++i) {
int wi;
scanf("%d", &wi);
if(wi % w)
suc = 0;
pq.push({wi, i});
ans[i].clear();
}
int sumd = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &d[i]);
sumd += d[i];
}
if(sumd % w)
suc = 0;
if(!suc) {
puts("-1");
} else {
for(int i = 1; i <= n; ++i) {
while(q.size() && i >= q.front().first) {
pq.push(q.front().second);
q.pop();
}
while(d[i]) {
if(i + w - 1 > n || pq.empty()) {
suc = 0;
break;
} else {
for(int k = i; k <= i + w - 1; ++k) {
if(d[k])
d[k]--;
else {
suc = 0;
break;
}
}
if(suc == 0)
break;
pair<int, int> tmp = pq.top();
pq.pop();
tmp.first -= w;
ans[tmp.second].push_back(i);
if(tmp.first)
q.push(make_pair(i + w + h, tmp));
//printf("assigned %d\n",tmp.second);
}
}
if(suc == 0)
break;
/*printf("i=%d\n", i);
for(int j = 1; j <= n; ++j) {
printf(" %d", d[j]);
}
printf("\n");*/
}
if(!suc) {
puts("-1");
} else {
puts("1");
for(int i = 1; i <= m; ++i) {
printf("%d", ans[i][0]);
for(int j = 1; j < ans[i].size(); ++j) {
printf(" %d", ans[i][j]);
}
puts("");
}
}
}
}
}
K - TV Show Game
听说还是什么2-SAT,不知,反正胆子大直接爆搜。爆搜容易T,每次都分两支,然后到最后才回溯就很难受。事实上填了一个不满足他的要求之后另外两个是可以立刻确定的,这样可以一次确定一大群,解决的办法就是提高他们的优先级然后重新排序使得搜索优先检测这些只有一条路走的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
char lamp[10005];
int cntR[10005];
int cntB[10005];
vector<int> aR[10005], aB[10005];
struct Hito {
int p1, p2, p3, fm;
char c1[2], c2[2], c3[2];
void set(int id) {
scanf("%d%s%d%s%d%s", &p1, c1, &p2, c2, &p3, c3);
if(c1[0] == 'R') {
cntR[p1]++;
aR[p1].push_back(id);
} else {
cntB[p1]++;
aB[p1].push_back(id);
}
if(c2[0] == 'R') {
cntR[p2]++;
aR[p2].push_back(id);
} else {
cntB[p2]++;
aB[p2].push_back(id);
}
if(c3[0] == 'R') {
cntR[p3]++;
aR[p3].push_back(id);
} else {
cntB[p3]++;
aB[p3].push_back(id);
}
fm = 0;
}
} hito[20005];
int resttop;
int rest[20005];
bool cmp(const int &a, const int &b) {
return abs(cntR[a]) < abs(cntR[b]);
}
int pri[20005];
bool cmp2(const int &a, const int &b) {
return pri[a] == pri[b] ? abs(cntR[a]) < abs(cntR[b]): pri[a]>pri[b];
}
bool updateaR(int id, int last) {
int n = aR[id].size();
for(int i = 0; i < n; ++i) {
hito[aR[id][i]].fm++;
if(hito[aR[id][i]].fm >= 2) {
for(int k = 0; k <= i; ++k)
hito[aR[id][k]].fm--;
return false;
}
}
for(int i = 0; i < n; ++i) {
pri[hito[aR[id][i]].p1]++;
pri[hito[aR[id][i]].p2]++;
pri[hito[aR[id][i]].p3]++;
}
sort(rest + last + 1, rest + 1 + resttop, cmp2);
return true;
}
void unupdateaR(int id) {
int n = aR[id].size();
for(int i = 0; i < n; ++i) {
hito[aR[id][i]].fm--;
pri[hito[aR[id][i]].p1]--;
pri[hito[aR[id][i]].p2]--;
pri[hito[aR[id][i]].p3]--;
}
}
bool updateaB(int id, int last) {
int n = aB[id].size();
for(int i = 0; i < n; ++i) {
hito[aB[id][i]].fm ++;
if(hito[aB[id][i]].fm >= 2) {
for(int k = 0; k <= i; ++k)
hito[aB[id][k]].fm--;
return false;
}
}
for(int i = 0; i < n; ++i) {
pri[hito[aB[id][i]].p1]++;
pri[hito[aB[id][i]].p2]++;
pri[hito[aB[id][i]].p3]++;
}
sort(rest + last + 1, rest + 1 + resttop, cmp2);
return true;
}
void unupdateaB(int id) {
int n = aB[id].size();
for(int i = 0; i < n; ++i) {
hito[aB[id][i]].fm--;
pri[hito[aB[id][i]].p1]--;
pri[hito[aB[id][i]].p2]--;
pri[hito[aB[id][i]].p3]--;
}
}
void show() {
for(int i = 1; i <= m; ++i) {
printf("%c", lamp[i] ? lamp[i] : 'O');
}
puts("");
}
bool suc;
void dfs(int id) {
if(suc)
return;
//show();
if(id > resttop) {
suc = true;
puts(lamp + 1);
return;
}
if(cntR[rest[id]] <= 0) {
lamp[rest[id]] = 'B';
if(updateaR(rest[id], id)) {
dfs(id + 1);
unupdateaR(rest[id]);
}
lamp[rest[id]] = 0;
lamp[rest[id]] = 'R';
if(updateaB(rest[id], id)) {
dfs(id + 1);
unupdateaB(rest[id]);
}
lamp[rest[id]] = 0;
} else {
lamp[rest[id]] = 'R';
if(updateaB(rest[id], id)) {
dfs(id + 1);
unupdateaB(rest[id]);
}
lamp[rest[id]] = 0;
lamp[rest[id]] = 'B';
if(updateaR(rest[id], id)) {
dfs(id + 1);
unupdateaR(rest[id]);
}
lamp[rest[id]] = 0;
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
while(~scanf("%d%d", &m, &n)) {
memset(lamp, 0, sizeof(lamp));
memset(cntR, 0, sizeof(cntR));
memset(cntB, 0, sizeof(cntB));
for(int i = 1; i <= m; ++i) {
aR[i].clear();
aB[i].clear();
}
for(int i = 1; i <= n; ++i) {
hito[i].set(i);
}
resttop = 0;
for(int i = 1; i <= m; ++i) {
if(cntR[i] == 0) {
lamp[i] = 'B';
} else if(cntB[i] == 0) {
lamp[i] = 'R';
} else {
rest[++resttop] = i;
}
cntR[i] -= cntB[i];
}
//show();
sort(rest + 1, rest + 1 + resttop, cmp);
//random_shuffle(rest + 1, rest + 1 + resttop);
suc = false;
lamp[m + 1] = '\0';
if(resttop == 0) {
puts(lamp + 1);
} else {
dfs(1);
if(suc) {
;
} else {
puts("-1");
}
}
}
}
F - Parentheses
和晓阳一起写的这个。晓阳提供了最重要的一个东西,就是两个括号外的运算符就直接improper,以及这个递归算法。我在上面打了几个补丁就过去了,首先是强判所有的error情况,简单来说括号不匹配、“+)”、“++”、“aa”之类的,还有就是去括号之后的符号串一定要上“a+a+a+a”这样的奇数长度。
然后调用晓阳的函数开始递归,找暴露在括号外的唯一运算符左右递归下去,找不到的话就说明整个串都在括号里,剥去一层括号递归下去。需要两个补丁,首先是特判“(a)”这种情况就是improper的,遇到直接标记improper(实际上可以在预处理做)。然后就是第一层不能剥括号,然后其余层只能剥一层括号,用一个额外标记来控制。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char s[10005];
char t[10005];
void go(int l, int r, bool &iserror, bool &isproper, bool fir = false) {
//printf("go[%d:%d]\n", l, r);
if(iserror)
return;
if(l == r) {
if(isalpha(s[l]))
return;
else {
iserror = true;
return;
}
}
if(l == r - 2) {
if(s[l] == '(' && s[r] == ')' && isalpha(s[l + 1])) {
isproper = false;
}
}
int cnt = 0, p = -1;
bool fal = 0;
for(int i = l; i <= r; ++i) {
if(s[i] == '(')
++cnt;
else if(s[i] == ')') {
--cnt;
if(cnt < 0) {
iserror = true;
return;
}
} else if(!isalpha(s[i])) {
if(cnt == 0) {
if(p == -1)
p = i;
else
isproper = false;
}
}
}
if(cnt) {
iserror = true;
return;
}
if(p == -1) {
if(fir == false) {
go(l + 1, r - 1, iserror, isproper, true);
} else {
isproper = false;
go(l + 1, r - 1, iserror, isproper);
}
} else {
go(l, p - 1, iserror, isproper);
go(p + 1, r, iserror, isproper);
}
}
bool isop(char ch) {
if(ch == '+' || ch == '-' || ch == '/' || ch == '*' || ch == '%')
return true;
return false;
}
int n = 0;
bool check1() {
int cnt = 0;
for(int i = 1; i <= n; ++i) {
if(s[i] == '(')
++cnt;
else if(s[i] == ')') {
--cnt;
if(cnt < 0)
return false;
} else if(isop(s[i])) {
if(i + 1 <= n && (s[i + 1] == ')' || isop(s[i + 1])))
return false;
if(i - 1 >= 1 && (s[i - 1] == '(' || isop(s[i - 1])))
return false;
} else {
if(i + 1 <= n && isalpha(s[i + 1]))
return false;
if(i - 1 >= 1 && isalpha(s[i - 1]))
return false;
if(i + 1 <= n && s[i + 1] == '(')
return false;
if(i - 1 >= 1 && s[i - 1] == ')')
return false;
}
}
if(cnt)
return false;
return true;
}
char tmp[10005];
bool check2() {
int cur = 0;
for(int i = 1; i <= n; ++i) {
if(s[i] == '(' || s[i] == ')')
continue;
tmp[++cur] = s[i];
}
tmp[cur + 1] = '\0';
if(cur % 2 == 0)
return false;
for(int i = 1; i <= cur; ++i) {
if(i & 1) {
if(isalpha(tmp[i]));
else
return false;
} else {
if(isop(tmp[i]));
else
return false;
}
}
return true;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // localll
fgets(t, 10000000, stdin);
/*while(cin >> t) */{
n = 0;
for(int i = 0, sz = strlen(t); i < sz; ++i) {
if(t[i] == ' ' || t[i] == '\n')
continue;
else
s[++n] = t[i];
}
s[n + 1] = '\n';
bool iserror = false, isproper = true;
if(check1() == 0) {
//括号不匹配/括号与运算符不匹配
iserror = true;
//cout << "?" << endl;
} else {
if(check2() == 0) {
iserror = true;
//cout << "!" << endl;
} else
go(1, n, iserror, isproper, true);
}
if(iserror) {
puts("error");
} else if(isproper) {
puts("proper");
} else {
puts("improper");
}
}
}
2018-2019 ACM-ICPC, Asia Seoul Regional Contest
标签:res shuff assign dom 遇到 put 奇数 说明 ems
原文地址:https://www.cnblogs.com/Inko/p/11565518.html