题意:
分析:
首先我们先把区间操作转化一下,因为区间操作的复杂度太高
我们把每一位上的值记为它和它前一位的异或值
这样 ([l,r]) 的区间翻转等价于 (l,r+1) 的单点异或,而我们的目标还是使得所有位置上的值为 (0)
像这样的点对关系我们可以看成 (l,r+1) 之间连接了一条无向边,我们要做的就是选择一些边,将两端的点值取反,使得每一个点的值为 0
然后我们建出图之后会发现,这是一个不连通的一般图,但是我们发现可以将这幅图转化为一些森林,因为如果选中的边成环了那么等价于没有选,所以每一个连通块都是一棵树,那么我们的问题转化为对于每一棵树选一些边,最后使得树上所有点的值为 (0) ,直接树形DP
对于节点 (u) 如果他的一个儿子值为 (1) 那么这条边必须选,同时对 (u) 和 (v) 的值取反,如果为 (0) 那么不选
最后如果根节点的值为 (1) 那么无解
tip: 因为区间操作转化为单点操作的时候会出现 (n+1) 点,但实际上 (n+1) 点的点值不存在,所以它为 (0,1) 都不影响结果,所以我们可以钦定 (n+1) 所在的连通块以 (n+1) 为根,不论结果如何不用管
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define fir first
#define sec second
#define inl inline
#define reg register
#define pb push_back
using namespace std;
namespace zzc
{
inl int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 2e5+5;
int n,m,cnt;
pii p[maxn];
int pos[maxn],fa[maxn],head[maxn];
bool vis[maxn],sta[maxn];
vector<int> ans;
struct edge
{
int to,nxt,id;
}e[maxn<<2];
inl void add(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].id=w;
e[cnt].nxt=head[u];
head[u]=cnt;
}
int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
inl bool connect(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx==fy) return true;
fa[fy]=fx;
return false;
}
bool dfs(int u)
{
bool res=sta[u];
vis[u]=true;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(vis[v]) continue;
bool tmp=dfs(v);
if(tmp) ans.pb(e[i].id);
res^=tmp;
}
return res;
}
void work()
{
int l,r;
n=read();m=read();
for(int i=1;i<=n+1;i++) fa[i]=i;
for(int i=1;i<=n;i++) p[i].fir=read(),p[i].sec=read();
sort(p+1,p+n+1);
for(int i=1;i<=n;i++) pos[i]=p[i].fir,sta[i]=p[i].sec;
for(int i=n;i;i--) sta[i]^=sta[i-1];
for(int i=1;i<=m;i++)
{
l=read();r=read();
l=lower_bound(pos+1,pos+n+1,l)-pos;
r=upper_bound(pos+1,pos+n+1,r)-pos;
if(!connect(l,r)) add(l,r,i),add(r,l,i);
}
dfs(n+1);
for(int i=1;i<=n;i++)
{
if(vis[i]) continue;
if(dfs(i))
{
puts("-1");
return ;
}
}
sort(ans.begin(),ans.end());
printf("%d
",ans.size());
for(int i=0,j=ans.size();i<j;i++) printf("%d ",ans[i]);
}
}
int main()
{
zzc::work();
return 0;
}