Stone的txl数
Time Limit: 1000MS
Memory Limit: 65536KB
Problem Description
Stone 将一个序列中 m 个区间的和命名为 txl 数(区间重叠部分只取一次)。
现在,Stone 从 QAQ 的桌子上获得了一个序列,他想知道这个序列的 txl 数是多少。
Input
输入数据有多组(数据组数不超过 50),到 EOF 结束。
每组数据第一行为两个数 n, m (1 <= n <= 10^5, 1 <= m <= 1000),分别代表序列的长度和区间的个数。
第二行为 n 个数代表该序列,(1 <= a[i] <= 10^7);接下来 m 行每行两个数 l, r (1 <= l <= r <= n),代表区间 [l, r]。
Output
对于每组数据,输出一行,表示该序列的 txl 数。
Example Input
10 3 1 2 3 4 5 6 7 8 9 10 1 3 2 4 3 5
Example Output
15
Hint
Author
Stone
注意long long
解法一:将区间排序,对区间进行更新累加
#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e6+10;
int n, m, l, r;
long long a[MAX], sum[MAX];
struct node
{
int l, r;
}lxt[1100];
void Sort(int l, int r)
{
for(int i = l; i<=r-1; ++i)
{
int k = i;
for(int j = i+1; j<=r; ++j)
{
if(lxt[k].l>lxt[j].l)
k = j;
}
if(k!=i)
swap(lxt[i], lxt[k]);
}
}
int main()
{
//freopen("data1.in", "r", stdin);
//freopen("data1.out", "w", stdout);
while(~scanf("%d%d", &n, &m))
{
sum[0] = 0;
for(int i = 1; i<=n; ++i)
{
scanf("%lld", &a[i]);
sum[i] = sum[i-1]+a[i];
}
long long ans = 0;
for(int i = 0; i<m; ++i)
scanf("%d%d", &lxt[i].l, &lxt[i].r);
Sort(0, m-1);
int ll = lxt[0].l, rr = lxt[0].r;
for(int i = 1; i<m; ++i)
{
if(lxt[i].l>rr)
{
ans+=sum[rr]-sum[ll-1];
ll = lxt[i].l;
rr = lxt[i].r;
}
else if(lxt[i].l>=ll&&lxt[i].r>=rr)
rr = lxt[i].r;
}
ans+=sum[rr]-sum[ll-1];
printf("%lld\n", ans);
}
return 0;
}
b数组用来标记,左端点b[i]+1, 右端点b[i]-1
更新b[i] = b[1]+b[2]+....+b[i]
对于数组b[ ],任意b[i] >=0
b[i]>0 该点在区间内
搞不懂的可以在纸上写写示例的b[i]
#include <bits/stdc++.h>
using namespace std;
int a[100086],b[100086],n,m,i,l,r;
long long ans;
int main(){
while(~scanf("%d %d",&n,&m)){
ans=0;
memset(b,0,sizeof(b));
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
while(m--){
scanf("%d %d",&l,&r);
b[l]++,b[r+1]--;
}
for(i=1;i<=n;i++){
b[i]+=b[i-1];
if(b[i])
ans+=a[i];
}
printf("%lld\n",ans);
}
return 0;
}