题意

线段(segment)

【题目描述】

给定n条线段,第i条线段的左端点为\(l_i\),右端点为\(r_i\)。第i条线段覆盖了点x当且仅当\(l_i ≤x ≤ r_i\)。

给定Q个询问,第i个询问给出了\(m_i\)个点。问有多少个线段覆盖了其中奇数个点。

【输入格式】

第一行一个正整数n,表示线段数量。

接下来n行,每行两个正整数\(l_i, r_i\),描述一条线段。

接下来一行一个正整数Q,表示询问数量。

接下来Q行,每行描述一个询问。第一个正整数\(m_i\)表示询问的点数,接下来\(m_i\)个整数表示每个点的坐标。

【输出格式】

输出Q行,分别表示每个询问的答案。

【输入样例】

5

1 4

2 5

1 5

3 3

1 1

3

3 1 2 5

2 1 5

4 1 2 4 5

【输出样例】

2

3

3

【数据范围与约定】

对于 100%的数据,\(n, Q ≤ 10^5, 1 ≤ l_i ≤ r_i ≤ n, 1 ≤ x ≤ n, ∑m_i ≤ 10_i\)。

数据编号 n Q \(m_i\)
0-1 ≤ 1000 ≤ 1000 ≤ 1000
2-3 \(≤ 10^5\) ≤ 200 \(≤ 10^5\)
4-6 \(≤ 10^5\) \(≤ 10^5\) ≤ 50
7-9 \(≤ 10^5\) \(≤ 10^5\) \(≤ 10^5\)

考场20分

要覆盖奇数个点,想到xor和为1,所以想法维护xor值的和。考虑一个点\(p\)的贡献,发现把线段左右端点拆开后,把\(l_i\le p\)的线段xor 1,把\(p \le r_i\)的线段xor 1,那么最终将所有线段的异或值取反就是我们想要的结果。

用kdtree维护线段,期望复杂度\(O(\sum m_i \sqrt{n})\)。

然后我跑了2s,而时限是1s,所以只有20分。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std; co int N=1e5+1;
int n,DIM,rt;
struct segment {int p[2];}sg[N];
il bool operator<(co segment&a,co segment&b) {return a.p[DIM]<b.p[DIM];}
struct node {int p[2],ch[2],mi[2],mx[2],siz,sum,val,tag,del;}tr[N];
#define lc tr[x].ch[0]
#define rc tr[x].ch[1]
il void up0(int x){
for(int i=0;i<2;++i){
tr[x].mi[i]=tr[x].mx[i]=tr[x].p[i];
if(lc)
tr[x].mi[i]=min(tr[x].mi[i],tr[lc].mi[i]),
tr[x].mx[i]=max(tr[x].mx[i],tr[lc].mx[i]);
if(rc)
tr[x].mi[i]=min(tr[x].mi[i],tr[rc].mi[i]),
tr[x].mx[i]=max(tr[x].mx[i],tr[rc].mx[i]);
}
tr[x].siz=tr[lc].siz+1+tr[rc].siz;
// cerr<<x<<" mi0="<<tr[x].mi[0]<<" mx0="<<tr[x].mx[0]
// <<" mi1="<<tr[x].mi[1]<<" mx1="<<tr[x].mx[1]<<endl;
}
int build(int l,int r,int dim){
if(l>r) return 0;
int x=l+r>>1;
DIM=dim,nth_element(sg+l,sg+x,sg+r+1),copy(sg[x].p,sg[x].p+2,tr[x].p);
lc=build(l,x-1,dim^1),rc=build(x+1,r,dim^1);
// cerr<<x<<" p0="<<tr[x].p[0]<<" p1="<<tr[x].p[1]<<" lc="<<lc<<" rc="<<rc<<endl;
return up0(x),x;
}
il void up(int x){
tr[x].sum=tr[lc].sum+tr[x].val+tr[rc].sum;
// cerr<<"x="<<x<<" lsum="<<tr[lc].sum<<" val="<<tr[x].val<<" rsum="<<tr[rc].sum<<endl;
}
il void down(int x){
if(tr[x].del){
if(lc)
tr[lc].del=1,tr[lc].sum=tr[lc].val=tr[lc].tag=0;
if(rc)
tr[rc].del=1,tr[rc].sum=tr[rc].val=tr[rc].tag=0;
tr[x].del=0;
}
if(tr[x].tag){
if(lc)
tr[lc].sum=tr[lc].siz-tr[lc].sum,tr[lc].val^=1,tr[lc].tag^=1;
if(rc)
tr[rc].sum=tr[rc].siz-tr[rc].sum,tr[rc].val^=1,tr[rc].tag^=1;
tr[x].tag=0;
}
}
void modify0(int x,int p){
if(!x||tr[x].mi[0]>p) return;
// cerr<<"x="<<x<<" p="<<p<<" mx0="<<tr[x].mx[0]<<endl;
if(tr[x].mx[0]<=p)
return tr[x].sum=tr[x].siz-tr[x].sum,tr[x].val^=1,tr[x].tag^=1,void();
down(x);
if(tr[x].p[0]<=p) tr[x].val^=1;
modify0(lc,p),modify0(rc,p);
return up(x);
}
void modify1(int x,int p){
if(!x||tr[x].mx[1]<p) return;
if(tr[x].mi[1]>=p)
return tr[x].sum=tr[x].siz-tr[x].sum,tr[x].val^=1,tr[x].tag^=1,void();
down(x);
if(tr[x].p[1]>=p) tr[x].val^=1;
modify1(lc,p),modify1(rc,p);
return up(x);
}
int p[N];
int main(){
freopen("segment.in","r",stdin),freopen("segment.out","w",stdout);
read(n);
for(int i=1;i<=n;++i) read(sg[i].p[0]),read(sg[i].p[1]);
rt=build(1,n,0);
// cerr<<"rt="<<rt<<endl;
for(int Q=read<int>(),m;Q--;){
read(m);
for(int i=1;i<=m;++i)
read(p[i]),modify0(rt,p[i]),modify1(rt,p[i]);
printf("%d\n",m&1?tr[rt].siz-tr[rt].sum:tr[rt].sum);
tr[rt].del=1,tr[rt].sum=tr[rt].val=tr[rt].tag=0;
}
return 0;
}

标解

树套树不能支持区间修改,这就是我打kdtree的原因。事实证明不能很好的维护。

那怎么办?按询问的点的个数分类暴力即可。

设一个块大小B,然后分两类:

  1. 对于点个数大于B的询问,我们用扫描的方式做。将所有点基数排序,做个横坐标的个数前缀和,然后扫描一遍所有的线段统计有多少段覆盖了奇数个点。复杂度\(O(m_i+n)\)
  2. 对于点个数小于B的询问,将点排序,因为要求覆盖了奇数个,所以枚举覆盖了哪奇数个,然后用主席树统计有多少线段刚好覆盖了这奇数个点。时间复杂度\(O(m_i^2\log n)\)。

然后块大小怎么分?造几组随机数据试一下就行了。\(B=0.8\sqrt{\frac n{\log n}}\)

#include <bits/stdc++.h>
using namespace std; void gi(int &x) {char ch = getchar(); x = 0; while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48, ch = getchar();}
void pi(int x) {if (x > 9) pi(x / 10); putchar(x % 10 + 48);} //begin persistent segment tree
const int sz = 5000000;
int a[sz], l[sz], r[sz], N, tn;
int add(int x, int p, int s = tn) {
int u = ++N; a[u] = a[x] + 1; l[u] = l[x]; r[u] = r[x];
if (s == 1) return u;
else if (p < (s >> 1)) l[u] = add(l[x], p, s >> 1);
else r[u] = add(r[x], p - (s >> 1), s >> 1);
return u;
}
int sum(int x, int p, int s = tn) {
if (s == 1) return a[x];
else if (p < (s >> 1)) return sum(l[x], p, s >> 1);
else return a[l[x]] + sum(r[x], p - (s >> 1), s >> 1);
}
//end persistent segment tree int n, q, cnt, x[233333], s[233333], root[233333];//x is query; s is used in brute force; root is the roots of persistent segment tree
pair <int, int> itv[233333];//intervals
#define L first
#define R second
int B; //actually query (l1+1, r1, l2+1, r2)
int query(int l1, int r1, int l2, int r2) {
return sum(root[r1], r2) + sum(root[l1], l2) - sum(root[l1], r2) - sum(root[r1], l2);
} void doit() {
int i, j, ans;
N = 0; gi(n); for (tn = 1; tn <= n; tn <<= 1);
for (i = 1; i <= n; i++) gi(itv[i].L), gi(itv[i].R);
sort(itv + 1, itv + n + 1);
for (i = j = 1; i <= n; i++) {
root[i] = root[i - 1];
for (; j <= n && itv[j].L <= i; j++)
root[i] = add(root[i], itv[j].R);
}
B = int(sqrt(n / log(n)) * 0.8); gi(q);
while (q--) {
gi(cnt); ans = 0;
for (i = 1; i <= cnt; i++) gi(x[i]);
if (cnt <= B) {
sort(x + 1, x + cnt + 1); x[cnt + 1] = n + 1;
for (i = 1; i <= cnt; i++)
for (j = i; j <= cnt; j += 2)
ans += query[i - 1], x[i], x[j] - 1, x[j + 1] - 1);
} else {
for (i = 1; i <= n; i++) s[i] = 0;
for (i = 1; i <= cnt; i++) s[x[i]]++;
for (i = 1; i <= n; i++) s[i] += s[i - 1];
for (i = 1; i <= n; i++) ans += (1 & (s[itv[i].R] ^ s[itv[i].L - 1]));
}
pi(ans); putchar('\n');
}
} int main() {freopen("segment.in","r",stdin);freopen("segment.out","w",stdout); doit(); return 0;}

test20190409 线段的更多相关文章

  1. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  2. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  3. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  4. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  5. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  6. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

  7. CF719E(线段树+矩阵快速幂)

    题意:给你一个数列a,a[i]表示斐波那契数列的下标为a[i],求区间对应斐波那契数列数字的和,还要求能够维护对区间内所有下标加d的操作 分析:线段树 线段树的每个节点表示(f[i],f[i-1])这 ...

  8. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  9. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

随机推荐

  1. jenkins+findbugs+checkstyle+PMD静态代码检查(二)

    可以根据自己的需求选中对应的插件进行配置(不一定非要同时配置三个插件) jenkins:持续集成的工具 fundbugs:检测代码静态错误的插件  例如:定义了没有用到的对象,string类型的比较使 ...

  2. S2 深入.NET和C#编程 笔试测试错题积累

    ---恢复内容开始--- <深入.NET平台和C#编程>内部测试题-笔试试卷错题积累 1: 1) 以下关于序列化和反序列化的描述错误的是( C). a) 序列化是将对象的状态存储到特定存储 ...

  3. js call回调的this指向问题

    function fn1(){ console.log(1); } function fn2(){ console.log(2); } fn1.call(fn2); //输出 1 fn1.call.c ...

  4. border_mode

    如果border_mode选择为same,那么卷积操作的输入和输出尺寸会保持一致.如果选择valid,那卷积过后,尺寸会变小 # apply a 3x3 convolution with 64 out ...

  5. Bluedroid: 音频数据的传输流程

    一. UIPC:   Audio Flinger获取到a2dp的hw module,然后蓝牙协议栈有专用于发送和接收media数据的线程,名称:btif_media_task.   蓝牙与Audio的 ...

  6. ubuntu多显示器单触摸屏校准

    多显示器单触摸屏屏幕校准 0.触摸屏重定向 sudo xinput map-to-output 13 DP1  #将触摸屏映射到指定的显示器 其中:13为触摸屏设备id,可通过 xinput命令查看 ...

  7. socket-重叠模型(overlap)

    socket-重叠模型(overlap) 重叠模型的基本设计原理便是让应用程序使用一个重叠的数据结构,一次投递一个或多个Winsock I/O请求.针对那些提交的请求,在它们完成之后,应用程序可为它们 ...

  8. SharePoint Framework 构建你的第一个web部件(三)

    博客地址:http://blog.csdn.net/FoxDave 本篇接上一讲,我们一起来看一下如何部署和测试本地开发的web部件. 在SharePoint中预览web部件 SharePoint ...

  9. 10个HTML5美化版复选框和单选框

    单选框Radiobox和复选框checkbox在网页中也十分常见,虽然它没有按钮的交互性强,但是如果能把它们像按钮那样美化一下,那也是非常不错的.本文收集了10个相对比较漂亮的美化版单选框和复选框,希 ...

  10. L323 英语有必要学语法吗

    The Agony and Ecstasy of Grammar “Underline a relative clause.” This challenge would give a lot of a ...