这个题我WA到第10次的时候气得我睡觉去了
以前的写法是把操作和源格子都存起来,每一步操作对所有格子都做一遍,总共只做一遍操作
AC的写法是把操作存起来,来一个格子就做一遍操作
道理上都是一样的,第一种写法死活过不去,拿着代码仓库里面的UVA512.in做输入和标答对了一遍,一模一样,绝对是in不够的缘故
除了EX操作之外,对输入的一串操作数排序,在上面二分找小于等于当前值的个数,比直接一个个比要快一些
图方便把4个操作写在一起了,简洁嘛。
代码:
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
using pa=pair<int,int>;
vector<string> com;
vector<vector<int>> opn;
vector<int> tv;//temporary vector
string str;
int kcase=1,npa,ncom,a,r,c;
pa p,ans;
vector<int>::iterator bsearch(vector<int>::iterator le,vector<int>::iterator ri,int value);
int main(){
ios_base::sync_with_stdio(false);
while(cin>>r>>c&&r+c){
if(kcase-1)
cout<<endl;
cout<<"Spreadsheet #"<<kcase++<<"\n";
cin>>ncom;
for(int i=0;i<ncom;++i){
cin>>str;
com.push_back(str);
if(str=="EX"){
tv.resize(4);
for(int& x:tv)cin>>x;
opn.push_back(tv);
}
else{
cin>>a;
tv.resize(a);
for(int& x:tv)cin>>x;
sort(tv.begin(),tv.end());
opn.push_back(tv);
}
}
cin>>npa;
while(npa--){
cin>>p.first>>p.second;
ans=p;
for(int i=0;i<ncom;++i)
if(com[i]=="EX"){
if(make_pair(opn[i][0],opn[i][1])==ans)
ans=make_pair(opn[i][2],opn[i][3]);
else if(make_pair(opn[i][2],opn[i][3])==ans)
ans=make_pair(opn[i][0],opn[i][1]);
}
else{
bool f=(com[i][1]=='R');
int sym=((com[i][0]=='I')<<1)-1;
auto tfun=[&f]()->int&{return f?ans.first:ans.second;};
if(ans.first==-1||ans.second==-1)
i=ncom;
else{
if(tfun()<opn[i][0])
continue;
else if(tfun()>opn[i].back())
tfun()+=sym*opn[i].size();
else{
auto it=bsearch(opn[i].begin(),opn[i].end()-1,tfun());
if(sym==-1&&tfun()==*it)
tfun()=-1;
else
tfun()+=sym*(it-opn[i].begin()+1);
}
}
}
cout<<"Cell data in ("<<p.first<<','<<p.second<<") ";
if(ans.first==-1||ans.second==-1)
cout<<"GONE\n";
else
cout<<"moved to ("<<ans.first<<','<<ans.second<<")\n";
}
com.clear();opn.clear();
}
return 0;
}
vector<int>::iterator bsearch(vector<int>::iterator le,vector<int>::iterator ri,int value){
auto mid=le;
while(ri>le){
mid=le+((ri+1-le)>>1);
if(*mid<=value)
le=mid;
else
ri=mid-1;
}
return le;
}