迟到了一个月的题解......
Logical Moos:
啊这题放在铜组T1雀食有点BT......
首先,我们关注l前第一和r最后那两组。如果这俩有一个是true,那答案肯定也是true。
否则,在l和r外边的都是false。那我们就只用仔细看l和r中间的玩意儿。对于l和r中间的每一组,只要第一组和最后一组都是false,那结果肯定也是false。
所以:如果换掉的对最后结果木有影响,那就不管;如果有,就换。
对于true的查询,我们必须再次检查该段是否包含l这组的第一个false,以及r这组的最后一个false。如果不是,那么即使我们将其余部分替换为true,结果也将还是false。
对于false的查询,如果输入是false,结果将为false。
我们每次只需记录每组中最左的false和最右的false,复杂度。
#include <bits/stdc++.h>
using namespace std;
string expr[maxn];
int group[maxn];
int main(){
int N,Q;
cin>>N>>Q;
for(int i=0;i<N;i++)
cin>>expr[i];
int idx=0;
for(int i=0;i<N;i++){
if(expr[i]=="or")
idx++;
else{
if(i%2==0)
group[i]=idx;
}
}
vector<int> first_false(idx+1,INF);
vector<int> last_false(idx+1,-1);
for(int i=0;i<N;i+=2){
int g=group[i];
if(expr[i]=="false"){
if(first_false[g]==INF)
first_false[g]=i;
last_false[g]=i;
}
}
int first_true=INF,last_true=-1;
for(int i=0;i<=idx;i++){
if(first_false[i]==INF){
if(first_true==INF)
first_true=i;
last_true=i;
}
}
while(Q--){
int l,r;
cin>>l>>r;
--l;
--r;
string query;
cin>>query;
int gl=group[l],gr=group[r];
if(first_true<gl || last_true>gr){
cout<<(query=="true"?'Y':'N');
continue;
}
if(query=="true")
cout<<(first_false[gl]<l || last_false[gr]>r?'N':'Y');
else
cout<<'Y';
}
return 0;
}
好长啊。。。
Walking Along a Fence:
我们用一个二维矩阵记录每个点沿栅栏的距离,我们按顺序读入栅栏,当我们这样做时,我们遍历栅栏上的每个点,在数组中标记每个点0,1,2,…;同时记录周长。由于篱笆最多访问每个点一次,时间复杂度为。
#include <bits/stdc++.h>
using namespace std;
const int MAX=200005;
struct loc{
int x;
int y;
}posts[MAX];
int perimeter,dist[1005][1005];
void walk(loc st,loc ed){
diff.x=ed.x-st.x,diff.y=ed.y-st.y;
int dis=abs(diff.x)+abs(diff.y);
diff.x=diff.x/dis,diff.y=diff.y/dis;
for(int i=0;i<dis;i++){
dist[st.x][st.y]=perimeter;
perimeter++;
st.x=st.x+diff.x,st.y=st.y+diff.y;
}
}
int main(){
int N,P;
cin>>N>>P;
for(int i=0;i<P;i++)
cin>>posts[i].x>>posts[i].y;
for(int i=0;i<P;i++)
walk(posts[i],posts[(i+1)%P]);
for(int i=0;i<N;i++){
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
int p1=dist[x1][y1];
int p2=dist[x2][y2];
int ans=abs(p1-p2);
ans=min(ans,perimeter-ans);
cout<<ans<<endl;
}
return 0;
}
Farmer John's Favorite Permutation:
Farmer Nhoj????????????????????????????????????????????????????????????
Emmmmmmmmmm,暴力的话肯定是不行的。那怎么办呢?
我们会发现,不管怎么动,1,永远不会动。所以,1,必然是那个活到最后的人。。否则直接不可以总司令然后走人。
如果不是-1,我们就把最后一个从h里踢出去,不管它。
那p的最小字典序一定满足。接下来,我们会想:只有一组这样的p吗?
我们知道,h都是不同的,看起来,如果存在一些映射到h的p,p必然是唯一的。
大家可以手推一下,把h和p都算出来,可以发现这两点:
1. 每个h里的元素都是不同的
2. p结尾的数正好是从h里消失的两个。
所以,只要确定了p结尾的数,就可以得出整个p。
#include <bits/stdc++.h>
using namespace std;
int main(){
int T;
cin>>T;
while(T--){
int N;
cin>>N;
vector<int> h(N-1);
for(auto &x:h)
cin>>x;
vector<bool> has(N+1);
for(int x:h)
has[x]=true;
vector<int> not_has;
for(int i=1;i<=N;i++){
if(!has[i])
not_has.push_back(i);
}
int cnt_one=count(h.begin(),h.end(),1);
if(not_has.size()>2 || h.back()!=1 || (not_has.size()==2 && cnt_one!=2)){
cout<<-1<<endl;
continue;
}
vector<int> p(N);
if(not_has.size()==1){
p[0]=1;
p[N-1]=not_has[0];
}
else{
p[0]=not_has[0];
p[N-1]=not_has[1];
}
int l=0,r=N-1;
for(int i=0;i<N-1;i++){
if(p[l]>p[r])
p[++l]=h[i];
else
p[--r]=h[i];
}
for(int i=0;i<N;i++)
cout<<p[i];
cout<<endl;
}
return 0;
}
好了,以上就是本期的全部内容了。我们下期再见!\(^o^)/~
友情提示:本期的代码都有问题,请不要无脑Ctrl C+Ctrl V