当前位置:   article > 正文

codeforces 1187D_codeforce写已经结束的比赛会加分吗

codeforce写已经结束的比赛会加分吗

传送门:https://codeforces.com/problemset/problem/1187/D

比赛中写了个假的FST了,不过还好E题是个水题而且写得够快,还是上了一大波分

那天晚上网友给了个hack数据

5
1 3 5 4 2
1 2 3 5 4

这个是YES,然后我就发现我没了,然后去hack了十多个人,结果发现edu赛后hack不加分。。。

后来补题瞄了一眼题解,发现把整体排序等价为两两交换后,关掉题解我瞎写了一通,然后WA再第20个点

5
1 3 4 5 2
1 2 4 5 3

这个是NO,然后通过这两个数据就能想到正解了。

对于线段树的每个下标i,我们存i这个数字下次在a数组中出现的位置。

非法情况就是当我要放一个数字i的时候,当前这个 i 是b中的第cnt[i]个i在a数组里应该放在idx=pos[i][cnt[i]-1],这个时候查看1-i中下一个要放的位置有没有小于idx的,如果有,那么就非法,输出NO。

上述例子的流程就是按b的顺序先放1,然后把1位置更新为n+1(后面已经没有1了),然后更新2为n+1,枚举到4的时候,发现1-3中1,2都为n+1,但是3为2,说明当前在a数组2号位置在b数组中实在4后面的,而3不能跟4交换,让3到4后面,所以非法

  1. #include<bits/stdc++.h>
  2. #define maxl 300010
  3. using namespace std;
  4. int n,ans;
  5. int a[maxl],b[maxl],cnt[maxl],len[maxl];
  6. vector <int> pos[maxl];
  7. struct node
  8. {
  9. int l,r;
  10. int mini;
  11. int tag;
  12. }tree[maxl*4];
  13. inline void build(int k,int l,int r)
  14. {
  15. tree[k].l=l;tree[k].r=r;
  16. if(l==r)
  17. {
  18. if(pos[l].size()==0)
  19. tree[k].mini=n+1;
  20. else
  21. tree[k].mini=pos[l][0];
  22. return;
  23. }
  24. int mid=(l+r)>>1;
  25. build(k<<1,l,mid);build(k<<1|1,mid+1,r);
  26. tree[k].mini=min(tree[k<<1].mini,tree[k<<1|1].mini);
  27. }
  28. inline void prework()
  29. {
  30. ans=1;
  31. scanf("%d",&n);
  32. for(int i=1;i<=n;i++)
  33. scanf("%d",&a[i]),cnt[i]=0,len[i]=0;
  34. for(int i=1;i<=n;i++)
  35. scanf("%d",&b[i]),pos[i].clear();
  36. for(int i=1;i<=n;i++)
  37. pos[a[i]].push_back(i),len[b[i]]++;
  38. for(int i=1;i<=n;i++)
  39. if(len[i]!=(int)(pos[i].size()))
  40. {
  41. ans=0;
  42. return;
  43. }
  44. build(1,1,n);
  45. }
  46. inline int qry(int k,int l,int r)
  47. {
  48. if(tree[k].l==l && tree[k].r==r)
  49. return tree[k].mini;
  50. int mid=(tree[k].l+tree[k].r)>>1;
  51. int ret;
  52. if(r<=mid)
  53. ret=qry(k<<1,l,r);
  54. else if(l>mid)
  55. ret=qry(k<<1|1,l,r);
  56. else
  57. ret=min(qry(k<<1,l,mid),qry(k<<1|1,mid+1,r));
  58. return ret;
  59. }
  60. inline void upd(int k,int l,int x)
  61. {
  62. int mid=(tree[k].l+tree[k].r)>>1;
  63. if(tree[k].l==tree[k].r)
  64. {
  65. tree[k].mini=x;
  66. return;
  67. }
  68. if(l<=mid)
  69. upd(k<<1,l,x);
  70. else
  71. upd(k<<1|1,l,x);
  72. tree[k].mini=min(tree[k<<1].mini,tree[k<<1|1].mini);
  73. }
  74. inline void mainwork()
  75. {
  76. if(!ans) return;
  77. int id;
  78. for(int i=1;i<=n;i++)
  79. {
  80. cnt[b[i]]++;
  81. id=pos[b[i]][cnt[b[i]]-1];
  82. if(qry(1,1,b[i])<id)
  83. {
  84. ans=0;
  85. return;
  86. }
  87. if(cnt[b[i]]==len[b[i]])
  88. upd(1,b[i],n+1);
  89. else
  90. upd(1,b[i],pos[b[i]][cnt[b[i]]]);
  91. }
  92. }
  93. inline void print()
  94. {
  95. if(ans)
  96. puts("YES");
  97. else
  98. puts("NO");
  99. }
  100. int main()
  101. {
  102. int t;
  103. scanf("%d",&t);
  104. for(int i=1;i<=t;i++)
  105. {
  106. prework();
  107. mainwork();
  108. print();
  109. }
  110. return 0;
  111. }

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号