称区间$[i,j]$为普通区间,当且仅当$j-i\ge 3$​​​且其操作两次内不会变为给定区间

结论:若$[i,j]$为普通区间,则$[i,j]$和$[i+1,j-1]$​​​​​​​​​​的状态(是否先手必胜)相同

(关于这个结论的正确性,不难分类讨论得到)

由此,对于普通区间不断缩小使其变为非普通区间,而非普通区间暴力枚举其变化,直至其长度为1或变为普通区间,显然这类区间至多只有$o(n)$个,因此记忆化后总复杂度也为$o(n)$

综上,只需要能快速实现缩小的过程即可,注意到和是相同的,以和为第一关键字,左端点为第二关键字在所有第2类的非普通区间中二分即可

(暴力的过程中判定区间是否为特殊区间也可以二分)

最终,总复杂度为$o((n+q)\log n)$​,可以通过

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 600005
4 int t,n,m,q,l,r,ans[N];
5 struct Data{
6 int l,r,p;
7 bool operator < (const Data &k)const{
8 return (l+r<k.l+k.r)||(l+r==k.l+k.r)&&(l<k.l);
9 }
10 bool operator == (const Data &k)const{
11 return (l==k.l)&&(r==k.r);
12 }
13 bool operator != (const Data &k)const{
14 return (l!=k.l)||(r!=k.r);
15 }
16 }a[N],b[N];
17 int find(int l,int r){
18 Data o=Data{l,r,0};
19 int p=lower_bound(b+1,b+m+1,o)-b;
20 if ((p>m)||(b[p]!=o))return -1;
21 return p;
22 }
23 int get_nex(int l,int r){
24 Data o=Data{l,r,0};
25 int p=lower_bound(b+1,b+m+1,o)-b;
26 if ((p<=m)&&(o.l+o.r==b[p].l+b[p].r))return b[p].l-o.l;
27 return (r-l-1>>1);
28 }
29 bool calc(int l,int r){
30 int p=find(l,r);
31 if (p>0){
32 if (b[p].p>=0)return b[p].p;
33 if (ans[p]>=0)return ans[p];
34 }
35 if (l==r)return 0;
36 if ((r-l>=3)&&(p<0)){
37 p=get_nex(l,r);
38 return calc(l+p,r-p);
39 }
40 int s=((calc(l,r-1)&calc(l+1,r))^1);
41 if (p>0)ans[p]=s;
42 return s;
43 }
44 int main(){
45 scanf("%d",&t);
46 while (t--){
47 scanf("%d%d",&n,&q);
48 for(int i=1;i<=n;i++){
49 scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].p);
50 a[i+n]=Data{a[i].l-1,a[i].r,-1};
51 a[i+n*2]=Data{a[i].l-2,a[i].r,-1};
52 a[i+n*3]=Data{a[i].l,a[i].r+1,-1};
53 a[i+n*4]=Data{a[i].l,a[i].r+2,-1};
54 a[i+n*5]=Data{a[i].l-1,a[i].r+1,-1};
55 }
56 sort(a+1,a+n*6+1);
57 m=0;
58 for(int i=1;i<=n*6;i++){
59 if ((a[i].l<=0)||(a[i].r>1e9))continue;
60 if ((!m)||(b[m]!=a[i]))b[++m]=a[i];
61 else{
62 if (b[m].p<0)b[m].p=a[i].p;
63 }
64 }
65 for(int i=1;i<=m;i++)ans[i]=-1;
66 for(int i=1;i<=q;i++){
67 scanf("%d%d",&l,&r);
68 printf("%d",calc(l,r));
69 }
70 printf("\n");
71 }
72 return 0;
73 }

[hdu7035]Game的更多相关文章

随机推荐

  1. WPF进阶技巧和实战08-依赖属性与绑定02

    将元素绑定在一起 数据绑定最简单的形式是:源对象是WPF元素而且源属性是依赖项属性.依赖项属性内置了更改通知支持,当源对象中改变依赖项属性时,会立即更新目标对象的绑定属性. 元素绑定到元素也是经常使用 ...

  2. 从零开始学算法---二叉平衡树(AVL树)

    先来了解一些基本概念: 1)什么是二叉平衡树? 之前我们了解过二叉查找树,我们说通常来讲, 对于一棵有n个节点的二叉查找树,查询一个节点的时间复杂度为log以2为底的N的对数. 通常来讲是这样的, 但 ...

  3. python3 拼接字符串方法

    python3.x拼接字符串一般有以下几种方法: 1. 直接通过(+)操作符拼接 1 2 s = 'Hello'+' '+'World'+'!' print(s) 输出结果:Hello World! ...

  4. Java秘诀!零基础怎样快速学习Java?

    对于零基础想学Java的朋友,其实一开始最应该做的就是定好学习目标和端正学习态度,切记不要三天打鱼两天晒网! 首先你是零基础,现在急需把Java学好,在保证学习质量的同时,用最短的时间学好Java应该 ...

  5. 字符串编码js第三方类库text-encoding

    GITHUB地址:https://github.com/BCode001/text-encoding

  6. The type name or alias SqlServer could not be resolved.Please check your configuration

    The type name or alias SqlServer could not be resolved.Please check your configuration file.... 检查一下 ...

  7. 每日总结:Java课堂测试第三阶段第二次优化 (四则运算) (2021.9.22)

    package jisuan2; import java.util.*;import java.util.Scanner; public class xiaoxue { public static v ...

  8. 题解 CF1103E Radix sum

    题目传送门 题目大意 给出一个\(n\)个数的序列\(a_{1,2,..,n}\),可以选\(n\)次,每次可以选与上次选的相同的数,问对于\(\forall p\in[0,n-1]\)满足选出来的数 ...

  9. 【c++ Prime 学习笔记】第11章 关联容器

    关联容器的元素按照关键字来保存和访问,而顺序容器的元素是按照在容器中的位置来保存和访问 关联容器支持高效的关键字查找和访问 2种关联容器: map中的元素是关键字-值对(key-value对),关键字 ...

  10. RBAC 权限管理模型

    一.RBAC模型--基于角色的访问控制 什么是RBAC RBAC(Role-Based Access Control)基于角色的访问控制.这是从传统的权限模型的基础之上,改进而来并且相当成熟的权限模型 ...