题目:
思路:先定义一个结构体用于存储ip前缀,然后按照题以模拟即可,有一个问题就是n最大是1e5,vector的erase是O(n)的,所以合并操作复杂度是O(nn),可能会超时,我的代码中第一步合并是
o(n)的,但是第二步是o(nn)的,可以改用list。
代码:
用vector的代码(100分)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
struct node {
int ip[4] , len , ip4[33];
unsigned int d;
node(string s) {
bool flag = 0;
int cnt = 0;
d = len = 0;
memset(ip,0,sizeof(ip));
for(int i = 0 ; i < s.length() ; i++) {
if(s[i] == '.')continue;
else if(s[i] == '/') {
flag = 1;continue;
}
else {
int t = 0;
while(isdigit(s[i])) {
t = t * 10 + s[i] - '0';
i++;
}
i--;
if(!flag)ip[cnt++] = t;
else len = t;
}
}
if(!len)len = cnt * 8;
cnt = 7;
for(int i = 0 ; i < 4 ; i++) {
d = d * 256 + ip[i];
int t = ip[i];
for(int j = cnt ; j >= cnt - 7 ; j--) {
ip4[j] = t % 2;
t /= 2;
}
cnt += 8;
}
}
node(){}
bool operator < (const node b) const {
return d < b.d || (d == b.d && len < b.len);
}
};
node a[maxn];
vector<node> ans;
bool vis[maxn];
bool judge(node b , node c) {
if(c.len < b.len)return false;
for(int i = 0 ; i < b.len ; i++) {
if(b.ip4[i] != c.ip4[i]) {
return false;
}
}
return true;
}
bool judge1(node b , node c) {
if(c.len != b.len || c.len == 0)return false;
for(int i = 0 ; i < b.len - 1 ; i++) {
if(b.ip4[i] != c.ip4[i])return false;
}
int len = b.len - 1;
if(b.ip4[len] != c.ip4[len]) return true;
else return false;
}
int main() {
int n;
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n;
for(int i = 0 ; i < n ; i++) {
string s;
cin >> s;
a[i] = node(s);
}
sort(a , a + n);
for(int i = 0 ; i < n ; ) {
int p = i;
i++;
while(i < n && !vis[i]) {
if(judge(a[p] , a[i])) {
vis[i] = 1;
//cout << i << endl;
i++;
}
else break;
}
}
for(int i = 0 ; i < n ; i++) {
if(!vis[i])ans.push_back(a[i]);
}
for(int i = 0 ; i < ans.size() - 1 ; i++) {
while(i < ans.size() - 1) {
if(judge1(ans[i] , ans[i + 1])) {
ans[i].len = ans[i].len - 1;
ans.erase(ans.begin() + i + 1);
if(i > 0)i--;
}
else break;
}
}
for(int i = 0 ; i < ans.size() ; i++) {
cout << ans[i].ip[0] << "."<<ans[i].ip[1] << "." << ans[i].ip[2] << "." << ans[i].ip[3] << "/" << ans[i].len<< "\n";
}
return 0;
}
用list的代码(100分)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
struct node {
int ip[4] , len , ip4[33];
unsigned int d;
node(string s) {
bool flag = 0;
int cnt = 0;
d = len = 0;
memset(ip,0,sizeof(ip));
for(int i = 0 ; i < s.length() ; i++) {
if(s[i] == '.')continue;
else if(s[i] == '/') {
flag = 1;continue;
}
else {
int t = 0;
while(isdigit(s[i])) {
t = t * 10 + s[i] - '0';
i++;
}
i--;
if(!flag)ip[cnt++] = t;
else len = t;
}
}
if(!len)len = cnt * 8;
cnt = 7;
for(int i = 0 ; i < 4 ; i++) {
d = d * 256 + ip[i];
int t = ip[i];
for(int j = cnt ; j >= cnt - 7 ; j--) {
ip4[j] = t % 2;
t /= 2;
}
cnt += 8;
}
}
node(){}
bool operator < (const node b) const {
return d < b.d || (d == b.d && len < b.len);
}
};
node a[maxn];
list<node> ans;
bool vis[maxn];
bool judge(node b , node c) {
if(c.len < b.len)return false;
for(int i = 0 ; i < b.len ; i++) {
if(b.ip4[i] != c.ip4[i]) {
return false;
}
}
return true;
}
bool judge1(node b , node c) {
if(c.len != b.len || c.len == 0)return false;
for(int i = 0 ; i < b.len - 1 ; i++) {
if(b.ip4[i] != c.ip4[i])return false;
}
int len = b.len - 1;
if(b.ip4[len] != c.ip4[len]) return true;
else return false;
}
int main() {
int n;
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n;
for(int i = 0 ; i < n ; i++) {
string s;
cin >> s;
a[i] = node(s);
}
sort(a , a + n);
for(int i = 0 ; i < n ; ) {
int p = i;
i++;
while(i < n && !vis[i]) {
if(judge(a[p] , a[i])) {
vis[i] = 1;
i++;
}
else break;
}
}
for(int i = 0 ; i < n ; i++) {
if(!vis[i])ans.push_back(a[i]);
}
for(auto t = ans.begin() ; t != ans.end() ; t++) {
auto t1 = t;
t1++;
while(t1 != ans.end() ) {
if(judge1(*t , *t1)) {
t -> len = t -> len - 1;
ans.erase(t1);
if(t != ans.begin())t--;
t1 = t; t1++;
}
else break;
}
}
for(auto t = ans.begin() ; t != ans.end() ; t++) {
cout << t -> ip[0] << "."<< t -> ip[1] << "." << t -> ip[2] << "." << t -> ip[3] << "/" << t -> len<< "\n";
}
return 0;
}