我正在尝试用C ++解决这个问题:
“给定一个整数序列S,找到一些递增的序列I,使得I中的每两个连续元素出现在S中,但是在I的第一个元素的相对侧。”
这是我开发的代码:
#include<iostream>
#include<set>
#include<vector>
using namespace std;
struct Element {
long long height;
long long acc;
long long con;
};
bool fncomp(Element* lhs, Element* rhs) {
return lhs->height < rhs->height;
}
int solution(vector<int> &H) {
// set up
int N = (int)H.size();
if (N == 0 || N == 1) return N;
long long sol = 0;
// build trees
bool(*fn_pt)(Element*, Element*) = fncomp;
set<Element*, bool(*)(Element*, Element*)> rightTree(fn_pt), leftTree(fn_pt);
set<Element*, bool(*)(Element*, Element*)>::iterator ri, li;
for (int i = 0; i < N; i++) {
Element* e = new Element;
e->acc = 0;
e->con = 0;
e->height = H[i];
rightTree.insert(e);
}
//tree elements set up
ri = --rightTree.end();
Element* elem = *ri;
elem->con = 1;
elem->acc = 1;
while (elem->height > H[0]) {
Element* succ = elem;
ri--;
elem = *ri;
elem->con = 1;
elem->acc = succ->acc + 1;
}
rightTree.erase(ri);
elem->con = elem->acc;
leftTree.insert(elem);
sol += elem->acc;
// main loop
Element* pE = new Element;
for (int j = 1; j < (N - 1); j++) {
// bad case
if (H[j] < H[j - 1]) {
///////
Element* nE = new Element;
nE->height = H[j];
pE->height = H[j - 1];
rightTree.erase(nE);
leftTree.insert(nE);
///////
li = leftTree.lower_bound(pE);
long ltAcc = (*li)->acc;
li--;
///////
ri = rightTree.lower_bound(pE);
long rtAcc = 0;
if (ri != rightTree.end()) rtAcc = (*ri)->acc;
ri--;
///////
while (ri != (--rightTree.begin()) && (*ri)->height > H[j]) {
if (fncomp(*ri, *li)) {
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
ltAcc = (*li)->acc;
--li;
}
else {
(*ri)->con = ltAcc + 1;
(*ri)->acc = ltAcc + 1 + rtAcc;
rtAcc = (*ri)->acc;
--ri;
}
}
while ((*li)->height > H[j]) {
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
ltAcc = (*li)->acc;
--li;
}
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
sol += (*li)->acc;
}
// good case
else {
Element* nE = new Element;
nE->height = H[j];
ri = rightTree.upper_bound(nE);
li = leftTree.upper_bound(nE);
rightTree.erase(nE);
if (li == leftTree.end() && ri == rightTree.end()) {
nE->con = 1;
nE->acc = 1;
}
else if (li != leftTree.end() && ri == rightTree.end()) {
nE->con = 1;
nE->acc = 1 + (*li)->acc;
}
else if (li == leftTree.end() && ri != rightTree.end()) {
nE->con = (*ri)->acc + 1;
nE->acc = nE->con;
}
else {
nE->con = (*ri)->acc + 1;
nE->acc = nE->con + (*li)->acc;
}
leftTree.insert(nE);
sol += nE->acc;
}
}
// final step
li = leftTree.upper_bound(*rightTree.begin());
while (li != leftTree.end()) {
sol++;
li++;
}
sol++;
return (int)(sol % 1000000007);
}
int main(int argc, char* argv[]) {
vector<int> H = { 13, 2, 5 };
cout << "sol: " << solution(H) << endl;
system("pause");
}
main
函数调用solution(vector<int> H)
。关键是,当参数具有特定值H = {13, 2, 5}
时,VC ++编译的程序给出输出值7
(这是正确的),但是GNU g ++编译程序给出的输出值为5
(同样clang编译的程序就像这样)。
我正在使用这个网站来测试不同的编译器 http://rextester.com/l/cpp_online_compiler_gcc
我试图弄清楚这种奇怪行为的原因,但没有找到任何相关信息。只有一个帖子处理类似的问题:
Different results VS C++ and GNU g++
这就是我在代码中使用long long
类型的原因,但问题仍然存在。
答案 0 :(得分:0)
问题是减少了序列开始--rightTree.begin()
正如我发现VC ++和GNU g ++在上述操作中的行为方式不同。以下是显示差异的代码,改编自http://www.cplusplus.com/forum/general/84609/:
#include<iostream>
#include<set>
using namespace std;
struct Element {
long long height;
long long acc;
long long con;
};
bool fncomp(Element* lhs, Element* rhs) {
return lhs->height < rhs->height;
}
int main(){
bool(*fn_pt)(Element*, Element*) = fncomp;
set<Element*, bool(*)(Element*, Element*)> rightTree(fn_pt);
set<Element*, bool(*)(Element*, Element*)>::iterator ri;
ri = rightTree.begin();
--ri;
++ri;
if(ri == rightTree.begin()) cout << "it works!" << endl;
}