菜菜太菜,但他不想种菜。
有 nn 块土地,每块土地有一个菜值。它们之间有 mm 条小路,每条连接两块土地,小路只能单向通行,不存在一条小路两端连接同一块土地,但可能存在两条小路两端连接的土地分别相同。如果存在一条从土地 uu 到土地 vv 的小路,则称 uu 能直接到达 vv。
菜菜可以购买一些土地,他必须在其中选择一块建造自己的家,所购买的剩下的土地都被作为菜地。因为菜菜不想种菜,所以他希望从他家能直接到达的土地中,一块菜地也没有(如果菜菜家不能直接到达任何一块土地,这也能满足他的愿望)。
菜菜提出了 qq 个问题,每个问题给出 L,RL,R ,询问如果他购买了第 LL 到第 RR 块之间的所有土地,那么所有满足他愿望的建造家的选址的菜值之和是多少?
对于这个问题 我们可以发现其实这个菜地是有自己的管辖范围的 他管辖的范围就是离他最近的l[i] 和 r[i] 只要所询问的区间在我这个范围只能那么我就可以加上这个菜地的值 ,对于m条小路的处理就是我们可以先预处理出l[i] and r[i] 预处理出这个之后 考虑对于询问进行离线处理 按照询问的右端点进行排序 然后一个一个处理询问 还要就是对于菜地值的和 利用树状数组进行维护菜地值的和
利用判断区间的右端点有没有超过当前的第i个的管辖范围来觉得是否消除第i个的影响 通过l是不是在 L 到 i 之间判断是否加入这个菜地的菜地值 通过一个vector<seg_> 来保存区间的影响是否 其中seg保存的是我当前第i个管辖的范围 在r[i] 这个点加入一个消除管辖范围的影响的seg_节点
具体看代码 询问离线加区间递增步步处理 还有消除影响 要好好记一下这个技巧
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define se second
#define fi first
#define pii pair<int,int>
#define lowbit(x) x&(-x)
typedef long long ll;
int lson(int p) {return p * 2;}
int rson(int p) {return p * 2 + 1;}
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const long long int inf = 1e17 + 10;
int n,m,q;
struct que_{
int l,r;
int id;
}a[maxn];
struct seq_{
int l,r;
ll w;
};
vector<seq_> v[maxn];
int l[maxn],r[maxn];
ll val[maxn],c[maxn];
ll t_ans[maxn];
ll ask(int x)
{
ll ans = 0;
for(;x; x -= lowbit(x)) ans += c[x];
return ans;
}
void add(int x,int y)
{
for(;x <= n; x += lowbit(x)) c[x] += y;
}
bool cmp(que_ x,que_ y)
{
return x.r < y.r;
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i = 1; i <= n; i++)
{
l[i] = 0,r[i] = n + 1;
scanf("%lld",&val[i]);
}
for(int i = 1; i <= m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(x > y) l[x] = max(l[x],y); // 检测范围
else r[x] = min(r[x],y);
}
for(int i = 1; i <= q; i++)
{
a[i].id = i;
scanf("%d%d",&a[i].l,&a[i].r);
}
sort(a + 1,a + q + 1,cmp);
for(int i = 1; i <= n; i++)
{
v[i].pb(seq_{l[i] + 1,i,val[i]}); // 增加我这个点i的影响
v[r[i]].pb(seq_{l[i] + 1,i,-val[i]}); // 当前询问超过我的r了 那么就将我这个影响消除掉
}
int l_ = 1;
for(int i = 1; i <= q; i++)
{
while(l_ <= a[i].r)
{
for(int j = 0; j < v[l_].size(); j++) // 消除前面的影响 增加自己当前的影响
{
add(v[l_][j].l,v[l_][j].w);
add(v[l_][j].r + 1,-v[l_][j].w);
}
l_++;
}
t_ans[a[i].id] = ask(a[i].l); // 询问一下菜地之和
}
ll ans = 0;
for(int i = 1; i <= q; i++)
{
//cout<<t_ans[i]<<endl;
ans ^= (t_ans[i] * (ll)i);
}
printf("%lld",ans);
return 0;
}