NOIP模拟2
下发文件
将军棋
又一道交互题.
发现这个无特殊性质的数据它的 Q 的使用次数较多,说明这道题需要继续按数据点编程.
特殊性质 A
扫一遍,每次找到相邻两个位置有不同的时 cnt + 1.
rll cnt=1;
if(t>=1&&t<=15)
{
g.emplace_back(1);
for(rll i=2;i<=n;i++) if(query(i-1,i)==2) g.emplace_back(++cnt); else g.emplace_back(cnt);
return g;
}
特殊性质 B
从当前位置往前找,每次找到有新的种类出现时,进行一次 check,如果数量和不算上该点一样的话说明就是这个类型. 否则继续找到下一个类型出现的位置.
if(t>=16&&t<=34)
{
g.emplace_back(1);
for(rll i=2;i<=n;i++)
{
rg bool flag[4]={0};
for(rll j=i-1;j;j--)
{
if(j==1||g[j-1]!=g[j-2]&&(!flag[g[j-1]]))
{
flag[g[j-1]]=1; rll cnt=(ll)flag[1]+flag[2]+flag[3]; if(query(j,i)==cnt) { g.emplace_back(g[j-1]);break; }
}
if((ll)flag[1]+flag[2]+flag[3]==2) { if(!flag[1]) g.emplace_back(1); else if(!flag[2]) g.emplace_back(2); else g.emplace_back(3); break; }
if(j==1) { if(!flag[2]) g.emplace_back(2); else g.emplace_back(3); }
}
}
return g;
}
特殊性质 C
可能是这些里面最难的了.
按照和 B 的方法找,最多会找 3000 次,超出这个范围. 所以需要修改一下,将其进行一个伪的二分,这样每次最多查询两个.
if(t>=35&&t<=48)
{
g.emplace_back(1); ls[1]=1; rll p[5]={0,1,2,3,4};
for(rll i=2;i<=n;i++)
{
sort(p+1,p+5,cmp);
if((!ls[p[2]])||query(ls[p[2]],i)<=2) { if(query(ls[p[1]],i)==1) g.emplace_back(p[1]); else g.emplace_back(p[2]); }
else { if((!ls[p[3]])||query(ls[p[3]],i)==3) g.emplace_back(p[3]); else g.emplace_back(p[4]); }
ls[g.back()]=i;
}
return g;
}
特殊性质 D
只需要扫一遍找到大小突然变化的地方,再扫一遍确定两个点的位置.
if(t>=49&&t<=60)
{
if(query(1,n)==n) { for(rll i=1;i<=n;i++) g.emplace_back(i); return g; }
for(rll i=2;i<=n;i++) if(query(1,i)^i) {
for(rll j=2;j<=i;j++) if(query(j,i)==i-j+1)
{
j--; for(rll k=1;k<=n;k++) if(k==i) g.emplace_back(j); else if(k>i) g.emplace_back(k-1); else g.emplace_back(k);
break;
}
break;
}
return g;
}
无特殊性质
将每一个点,它的前面进行二分,找出在这个数之前出现的那一个值.
g.emplace_back(1);a[1][1]=1;
for(rll i=2,l,r,mid,ans;i<=n;i++)
{
a[1][i]=query(1,i);if(a[1][i]==a[1][i-1]+1) { g.emplace_back(++cnt); for(rll j=2;j<=i;j++) a[j][i]=a[j][i-1]+1; continue; }
l=1,r=i-1,ans=0; while(l<=r)
{
mid=(l+r)>>1;
// cout<<mid<<' '<<i<<' '<<query(mid,i)<<' '<<a[mid][i-1]<<endl;
if(query(mid,i)==a[mid][i-1]) ans=mid,l=mid+1; else r=mid-1;
}
ans=g[ans-1]; memset(sum,0,sizeof(sum)); g.emplace_back(ans);
for(rll j=i,tot=0;j>1;j--) { if(!sum[g[j-1]]) tot++; sum[g[j-1]]=1;a[j][i]=tot;/*cout<<j<<' '<<i<<' '<<tot<<endl;*/ }
}
// for(rll i=0;i<g.size();i++) write(g[i]),put_;putn;
return g;
代码部分可能在编辑时有缺少部分符号,不影响理解. 如有也请留言,我会第一时间修改.
记住交互题里多余的函数一定要删掉!删掉!删掉! 因为 read()
函数名重复 CE 爆了 86 分.
小明的变换
发现一个很有趣的规律:把每一个数不断往后放,和先移前面再移后面,抑或是先移后面再移前面,这样最终都能够达到一样的序列.
所以,每次找到第一处不相同的或是数目不一样的.
找到不相同的就将它不断向后面移,如果移不了(后面没有这个数了)就是无解.
数目不一样的话就记录一下缺多少,然后再向后面要. 中间的部分还是按照不同的处理.
如果多了,就把多余的部分按照不同的处理.
具体的还需要预处理一个前缀和,代表每一串连续的数有多少个. 每次直接跳到这一相同数段的最后一个位置即可.
就这玩意我还调了一个多小时
点击查看代码
#include<bits/extc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 1000001
#define pll pair<ll,ll>
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rg bool f=0;rll x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10);putchar(x%10|'0'); }
ll t,n,c[maxn],d[maxn],nx[maxn];
vector<pll> a,b;
__gnu_pbds::gp_hash_table<ll,ll> mp;
bool fl;
int main()
{
freopen("trans.in","r",stdin); freopen("trans.out","w",stdout);
t=read(); for(rll k=1;k<=t;k++)
{
a.clear();b.clear(); n=read(); for(rll i=1;i<=n;i++) c[i]=read(); for(rll i=1;i<=n;i++) d[i]=read();
a.emplace_back(0,0);b.emplace_back(0,0); mp.clear(); c[n+1]=d[n+1]=0;
// if(k==31) {for(rll i=1;i<=n;i++) write(c[i]),put_;putn;for(rll i=1;i<=n;i++) write(d[i]),put_;putn;}
fl=0; for(rll i=1;i<=n;i++) if(c[i]^d[i]) { fl=1;break; } if(!fl) { puts("Yes"); continue; }
for(rll i=n;i;i--) if(c[i]^c[i+1]) { if(mp[c[i]]) nx[i]=mp[c[i]]; else nx[i]=0; mp[c[i]]=i; }
for(rll i=1,cnt=0;i<=n;i++) { if(c[i]==c[i-1]) cnt++; else cnt=1; a.emplace_back(c[i],cnt); }
for(rll i=1,cnt=0;i<=n;i++) { if(d[i]==d[i-1]) cnt++; else cnt=1; b.emplace_back(d[i],cnt); }
fl=0; sort(c+1,c+n+1);sort(d+1,d+n+1); for(rll i=1;i<=n;i++) if(c[i]^d[i]) { fl=1;break; } if(fl) { puts("No"); continue; }
for(rll i=1,j=1;i<=n&&j<=n;i++,j++)
{
// cout<<"00\n";
while(b[j].first==b[j+1].first) j++;
// for(rll i=1;i<=n;i++) cout<<a[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<a[i].second<<' ';cout<<endl;
// for(rll i=1;i<=n;i++) cout<<b[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<b[i].second<<' ';cout<<endl;
// cout<<'#'<<i<<' '<<j<<endl;
// puts("Continue...");getchar();
rll cnt=0;
while(cnt<b[j].second)
{
while(a[i].first==a[i+1].first) i++;
if(a[i].first==b[j].first&&a[i].second+cnt==b[j].second) break;
if(a[i].first==b[j].first)
{
if(a[i].second>=(b[j].second-cnt))
{
if(a[i].second>(b[j].second-cnt)&&(!nx[i]))
{
// cout<<"*0 "<<i<<' '<<j<<' '<<a[i].first<<' '<<a[i].second<<' '<<b[j].second<<' '<<cnt<<endl;
// for(rll i=1;i<=n;i++) cout<<a[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<a[i].second<<' ';cout<<endl;
// for(rll i=1;i<=n;i++) cout<<b[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<b[i].second<<' ';cout<<endl;
fl=1;break;
}
// cout<<"*1 "<<i<<' '<<j<<' '<<a[i].first<<' '<<a[i].second<<' '<<b[j].second<<' '<<cnt<<endl;
a[nx[i]].second+=a[i].second-(b[j].second-cnt);a[i].second=(b[j].second-cnt);
// for(rll i=1;i<=n;i++) cout<<a[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<a[i].second<<' ';cout<<endl;
// for(rll i=1;i<=n;i++) cout<<b[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<b[i].second<<' ';cout<<endl;
break;
}
else
{
// cout<<"*2 "<<i<<' '<<j<<' '<<a[i].first<<' '<<a[i].second<<' '<<b[j].second<<' '<<cnt<<endl;
cnt+=a[i].second,a[i].second=0,i++;
// for(rll i=1;i<=n;i++) cout<<a[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<a[i].second<<' ';cout<<endl;
// for(rll i=1;i<=n;i++) cout<<b[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<b[i].second<<' ';cout<<endl;
}
}
else
{
if(!nx[i])
{
// cout<<"*3 "<<i<<' '<<j<<' '<<a[i].first<<' '<<a[i].second<<' '<<b[j].second<<' '<<cnt<<endl;
// for(rll i=1;i<=n;i++) cout<<a[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<a[i].second<<' ';cout<<endl;
// for(rll i=1;i<=n;i++) cout<<b[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<b[i].second<<' ';cout<<endl;
fl=1;break;
}
a[nx[i]].second+=a[i].second;a[i].second=0;i++;
// cout<<"*4 "<<i<<' '<<j<<' '<<a[i].first<<' '<<a[i].second<<' '<<b[j].second<<' '<<cnt<<endl;
// for(rll i=1;i<=n;i++) cout<<a[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<a[i].second<<' ';cout<<endl;
// for(rll i=1;i<=n;i++) cout<<b[i].first<<' ';cout<<endl;for(rll i=1;i<=n;i++) cout<<b[i].second<<' ';cout<<endl;
}
if(i>n) { /*cout<<"-1\n";*/fl=1;break; }
}
if(fl) break;
}
puts(fl?"NO":"YES");
}
return 0;
}
小明过生日
容易发现,一个合法的序列只有在两端是奇数中间是偶数时才可以.
为什么呢?可以考虑:一个奇数长的段会导致错位,只有错开一位才能够将这一段回文变成一个唯一可能的段(就是全部是同一个字母).
所以,如果多于两个奇数,一定不合法. 否则,把奇数单独拎出来,一个放在前面,如果有另一个就放在最后面(因为一个奇数只会改变它后面所有数的错位状态).
当 m = 1 时,特判一下,把它一个和分解为两个的情况输出(当然还要再特判 n = 1的情况).
点击查看代码
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
#define pll pair<ll,ll>
#define maxn 1001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rg bool f=0;rll x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10);putchar(x%10|'0'); }
ll n,m,cnt,a[maxn];
vector<ll> b;
inline bool cmp(rll x,rll y) { return (x&1)>(y&1); }
int main()
{
freopen("birth.in","r",stdin); freopen("birth.out","w",stdout);
n=read();m=read(); for(rll i=1;i<=m;i++) cnt+=(a[i]=read())&1;// ,cout<<cnt<<endl;
if(cnt>2) { puts("-1"); return 0; }
if(m==1) { if(a[1]==1) puts("1\n1\n1"); else write(a[1]),putn,write(2),putn,write(a[1]-1),put_,putchar('1'); return 0; }
sort(a+1,a+m+1,cmp);write(a[1]),put_; for(rll i=3;i<=m;i++) write(a[i]),put_; write(a[2]);putn;
b.emplace_back(a[1]+1); for(rll i=3;i<=m;i++) b.emplace_back(a[i]); if(a[2]^1) b.emplace_back(a[2]-1);
write(b.size());putn;for(rll i=0;i<b.size();i++) write(b[i]),put_;
return 0;
}
小明爱数数
原题:CF1608F.
显然大神说的要比我这个蒟蒻说的详细,就不想写了. 以后有时间再认真写一遍(估计可能没有,有也忘了)
--END--
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/16878078.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!