版权声明:转载请注明出处,欢迎讨论,共同进步,QQ:1051780721 https://blog.csdn.net/ACM2017/article/details/82265417
Problem:https://odzkskevi.qnssl.com/da9adfb686ef541a14cec9856721130a?v=1535198186
Source:http://codeforces.com/gym/101572/attachments
Solution
//This is my AC version
#include<bits/stdc++.h>
using namespace std;
const int N = 100000;
const int MX = 360;
int n;
int card[N][3], ID[N], cnt_ColAngle[3][MX];
int LA[3][MX], RA[3][MX];
int score_CA[3][MX], score_lab[N];
struct data {
int id, score;
data () {}
data (int a,int b) {
id = a, score = b;
}
bool operator<(const data &b) const {
if (score == b.score) return id > b.id;
return score < b.score;
}
};
set<data> S;
vector<int> A[3];
set<int> lab[3][MX];
map<int,int> Map;
int calc_lab(int p) { // Calculate the score of card with label p.
return score_CA[0][card[p][0]] + score_CA[1][card[p][1]] + score_CA[2][card[p][2]];
}
int calc_ColAngle(int col, int x) { //Calculate the score of angle x, color col.
if (cnt_ColAngle[col][x] > 1) return 0; // If there are more than one this color of angles, the uniqueness value of them should be zero.
int res = RA[col][x] - LA[col][x];
return res>0 ? res : res + 360;
}
void Update(int p) {// After sold the card with label p whose id is ID[p] off, we need to check if it's necessary to update the angles and cards besides it.
int x, tmp;
set<int>::iterator ip;
for (int col = 0; col < 3; ++col) {
x = card[p][col]; // card p's angle based on color col.
cnt_ColAngle[col][x]--;
if (cnt_ColAngle[col][x] > 1) continue; //If this color still has more than one angles valued x, we have to do nothing.
else if (cnt_ColAngle[col][x] == 1) {//Still has one left, score_CA[col][x] will change into nonzero; check whether cards in S need to be update.
for (ip = lab[col][x].begin(); ip != lab[col][x].end(); ip++) {//Update cards with angle x based on color col which lab is *ip.
score_CA[col][x] = calc_ColAngle(col,x);
if (score_lab[*ip] != calc_lab(*ip)) {
S.erase(S.find(data(ID[*ip],score_lab[*ip])));
S.insert(data(ID[*ip],score_lab[*ip]=calc_lab(*ip)));
}
}//Summarize: Change one angle, Update one angle, many cards.
} else {//None left, update both angles on the left and on the right; check cards in S.
int lA = LA[col][x];
int rA = RA[col][x];
LA[col][rA] = lA;
RA[col][lA] = rA;
tmp = calc_ColAngle(col, lA);
if (score_CA[col][lA] != tmp) {
score_CA[col][lA] = tmp;
for (ip = lab[col][lA].begin(); ip != lab[col][lA].end(); ip++) {
S.erase(S.find(data(ID[*ip], score_lab[*ip])));
S.insert(data(ID[*ip], score_lab[*ip] = calc_lab(*ip)));
}
}
tmp = calc_ColAngle(col, rA);
if (score_CA[col][rA] != tmp) {
score_CA[col][rA] = tmp;
for (ip = lab[col][rA].begin(); ip != lab[col][rA].end(); ip++) {
S.erase(S.find(data(ID[*ip], score_lab[*ip])));
S.insert(data(ID[*ip], score_lab[*ip] = calc_lab(*ip)));
}
}
}//Summarize: Change one angle, Update two angle, many many cards.
}
}
void Input() {
int x;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < 3; ++j) {
scanf("%d", &x);
card[i][j] = x;
if (cnt_ColAngle[j][x] == 0) A[j].push_back(x);
cnt_ColAngle[j][x]++;
lab[j][x].insert(i);
}
scanf("%d", &ID[i]);
Map[ID[i]]=i;
}
}
void ScoringOnAngle() {
int len;
for (int col = 0; col < 3; ++col) {
sort(A[col].begin(), A[col].end());
len = A[col].size();
for (int i = 0; i + 1 < len; ++i) {//0<=i,i+1<=size()-1
LA[col][A[col][i + 1]] = A[col][i];
RA[col][A[col][i]] = A[col][i + 1];
}
LA[col][A[col][0]] = A[col][len - 1];
RA[col][A[col][len - 1]] = A[col][0];
for (int i = 0; i < len; ++i)
score_CA[col][A[col][i]] += calc_ColAngle(col, A[col][i]);
}
}
void ScoringOnLab() {
for (int i = 0; i < n; ++i) {
score_lab[i] = calc_lab(i);
//printf("i=%d scoreID=%d\n",i,score_lab[i]);
S.insert(data(ID[i], score_lab[i]));
}
}
void Output() {
set<data>::iterator ipd;
int ip;
while (!S.empty()) {
ipd = S.begin();
ip = Map[ipd->id];
printf("%d\n", ipd->id);
for (int col = 0; col < 3; ++col)
lab[col][card[ip][col]].erase(ip);
S.erase(ipd);
Update(ip);
}
}
int main() {
//freopen("../in", "r", stdin);
Input();
ScoringOnAngle();
ScoringOnLab();
Output();
return 0;
}
//This is my RE version
#include<bits/stdc++.h>
using namespace std;
const int N = 100000;
const int MX = 360;
int n;
int card[N][3], ID[N], cnt_ColAngle[3][MX];
int LA[3][MX], RA[3][MX];
int score_CA[3][MX], score_lab[N];
struct data {
int id, score;
data () {}
data (int a,int b) {
id = a, score = b;
}
bool operator<(const data &b) const {
if (score == b.score) return ID[id] > ID[b.id];
return score < b.score;
}
};
set<data> S;
vector<int> A[3];
set<int> lab[3][MX];
int calc_lab(int p) { // Calculate the score of card with label p.
return score_CA[0][card[p][0]] + score_CA[1][card[p][1]] + score_CA[2][card[p][2]];
}
int calc_ColAngle(int col, int x) { //Calculate the score of angle x, color col.
if (cnt_ColAngle[col][x] > 1) return 0; // If there are more than one this color of angles, the uniqueness value of them should be zero.
int res = RA[col][x] - LA[col][x];
return res>0 ? res : res + 360;
}
void Update(int p) {// After sold the card with label p whose id is ID[p] off, we need to check if it's necessary to update the angles and cards besides it.
int x, tmp;
set<int>::iterator ip;
for (int col = 0; col < 3; ++col) {
x = card[p][col]; // card p's angle based on color col.
cnt_ColAngle[col][x]--;
if (cnt_ColAngle[col][x] > 1) continue; //If this color still has more than one angles valued x, we have to do nothing.
else if (cnt_ColAngle[col][x] == 1) {//Still has one left, score_CA[col][x] will change into nonzero; check whether cards in S need to be update.
for (ip = lab[col][x].begin(); ip != lab[col][x].end(); ip++) {//Update cards with angle x based on color col which lab is *ip.
score_CA[col][x] = calc_ColAngle(col,x);
if (score_lab[*ip] != calc_lab(*ip)) {
S.erase(S.find(data(*ip,score_lab[*ip])));
S.insert(data(*ip,score_lab[*ip]=calc_lab(*ip)));
}
}//Summarize: Change one angle, Update one angle, many cards.
} else {//None left, update both angles on the left and on the right; check cards in S.
int lA = LA[col][x];
int rA = RA[col][x];
LA[col][rA] = lA;
RA[col][lA] = rA;
tmp = calc_ColAngle(col, lA);
if (score_CA[col][lA] != tmp) {
score_CA[col][lA] = tmp;
for (ip = lab[col][lA].begin(); ip != lab[col][lA].end(); ip++) {
S.erase(S.find(data(*ip, score_lab[*ip])));
S.insert(data(*ip, score_lab[*ip] = calc_lab(*ip)));
}
}
tmp = calc_ColAngle(col, rA);
if (score_CA[col][rA] != tmp) {
score_CA[col][rA] = tmp;
for (ip = lab[col][rA].begin(); ip != lab[col][rA].end(); ip++) {
S.erase(S.find(data(*ip, score_lab[*ip])));
S.insert(data(*ip, score_lab[*ip] = calc_lab(*ip)));
}
}
}//Summarize: Change one angle, Update two angle, many many cards.
}
}
void Input() {
int x;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < 3; ++j) {
scanf("%d", &x);
card[i][j] = x;
if (cnt_ColAngle[j][x] == 0) A[j].push_back(x);
cnt_ColAngle[j][x]++;
lab[j][x].insert(i);
}
scanf("%d", &ID[i]);
}
}
void ScoringOnAngle() {
int len;
for (int col = 0; col < 3; ++col) {
sort(A[col].begin(), A[col].end());
len = A[col].size();
for (int i = 0; i + 1 < len; ++i) {//0<=i,i+1<=size()-1
LA[col][A[col][i + 1]] = A[col][i];
RA[col][A[col][i]] = A[col][i + 1];
}
LA[col][A[col][0]] = A[col][len - 1];
RA[col][A[col][len - 1]] = A[col][0];
for (int i = 0; i < len; ++i)
score_CA[col][A[col][i]] += calc_ColAngle(col, A[col][i]);
}
}
void ScoringOnLab() {
for (int i = 0; i < n; ++i) {
score_lab[i] = calc_lab(i);
//printf("i=%d scoreID=%d\n",i,score_lab[i]);
S.insert(data(i, score_lab[i]));
}
}
void Output() {
set<data>::iterator ipd;
while (!S.empty()) {
ipd = S.begin();
printf("%d\n", ID[ipd->id]);
for (int col = 0; col < 3; ++col)
lab[col][card[ipd->id][col]].erase(ipd->id);
S.erase(ipd);
Update(ipd->id);
}
}
int main() {
//freopen("../in", "r", stdin);
Input();
ScoringOnAngle();
ScoringOnLab();
Output();
return 0;
}
//Test Code
//#include <bits/stdc++.h>
//using namespace std;
//int a[10] = {1,5,3,2,6,0,4};
//int b[10] = {0,1,2,3,4,5,6};
//int main() {
// for (int i=0;i<5;++i)
// for (int j=i+1;j<6;++j)
// if (a[b[i]]<a[b[j]]) swap(b[i],b[j]);
// for (int i=0;i<6;++i) printf("%5d",a[b[i]]);
// return 0;
//}
tmw?