称区间$[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. Python技法-序列拆分

    Python中的任何序列(可迭代的对象)都可以通过赋值操作进行拆分,包括但不限于元组.列表.字符串.文件.迭代器.生成器等. 元组拆分 元组拆分是最为常见的一种拆分,示例如下: p = (4, 5) ...

  2. requirejs的加载原理 - 场景1. 定义一个require依赖a模块

    我们学习一个新的技术,熟练的使用之后,就应该去探索它的原理.这篇文章我们来探索下requirejs的原理. 从4个场景来探索requirejs的原理 场景1. 定义一个require依赖b模块 场景2 ...

  3. Dapr + .NET Core实战(十二)服务调用之GRPC

    什么是GRPC gRPC 是一种与语言无关的高性能远程过程调用 (RPC) 框架. gRPC 的主要优点是: 高性能轻量级 RPC 框架. 协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的 ...

  4. Idea进行java应用的远程调试Remote debugging

    本文可以解决如下两个问题: 1.如何处理和调试那些只发生在生产环境(或其他远程环境)而本地开发环境可能没办法重现的"问题". 2.只有一个可以部署的war/jar包,只有class ...

  5. 单体应用 适合采用 dapr 构建吗?

    缘起今天在微信群里有同学问 "纯.net 项目,有必要上dapr吗?" 当时不假思索的说不是微服务没必要,其他群友也说没必要.下午细想了一下,觉得这个和微服务没有关系,如果我的应用 ...

  6. Redis分布式锁的正确实现方式[转载]

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  7. MySQL:基础语法-3

    MySQL:基础语法-3 记录一下 MySQL 基础的一些语法,便于查询,该部分内容主要是参考:bilibili 上 黑马程序员 的课程而做的笔记,由于时间有点久了,课程地址忘记了 上文MySQL:基 ...

  8. beta事后分析

    设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 软件要解决的问题是是开发一个简易方便,为用户带来便捷且功能齐全的表情包管理小程序: 预期的典型用户 ...

  9. 2021.10.26考试总结[冲刺NOIP模拟16]

    T1 树上的数 \(DFS\)一遍.结构体存边好像更快? \(code:\) T1 #include<bits/stdc++.h> using namespace std; namespa ...

  10. camera isp(Image Signal Processor)

    1. 目标[52RD.com] 手机摄像头模组用ISP功能模块的市场走向及研发方向.为能够正确认识手机摄像模组行业提供技术及市场依据.[52RD.com] 2. ISP在模组上的应用原理[52RD.c ...