Compass Card Sales Gym - 101572C NCPC2017

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?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值