UVA 12663 (线段树区间更新+二分查找,Q次区间更新后,求满足结果大于K的个数)

来源:互联网 发布:杭州市行知小学校地址 编辑:程序博客网 时间:2024/06/09 18:54


看见这种区间更新的题目,首先想到的就是线段树的区间更新。本体套用线段树的区间更新模板,更新的区间要二分去找。

#include<stdio.h>#include<string.h>#include<algorithm>#define MAX 200009#define LL long long intusing namespace std;LL a[MAX],cnt;struct Node {    LL L;    LL R;    Node *pL;    Node *pR;    LL sum;    LL add;} tree[4*MAX];LL n,m,k;LL ans;LL mid(struct Node *root) {    return (root->L+root->R)/2;}LL Search(LL low,LL high,LL goal) {    LL mid;    while(low<=high){        mid=(low+high)/2;        if(goal<=a[mid]){            high=mid-1;        }else{            low=mid+1;        }    }    return low;}void build(struct Node *root,LL L,LL R) {    root->L=L;    root->R=R;    root->add=0;    if(L==R) return;    LL midd=(L+R)/2;    cnt++;    root->pL=tree+cnt;    build(root->pL,L,midd);    cnt++;    root->pR=tree+cnt;    build(root->pR,midd+1,R);}void add(struct Node *root, LL L, LL R, LL val) {    if(root->L==L&&root->R==R) {        root->add+=val;        return;    }    LL midd=mid(root);    if(R<=midd)add(root->pL, L, R, val);    else if(L>midd) add(root->pR, L, R, val);    else {        add(root->pL, L, mid(root), val);        add(root->pR, mid(root)+1, R,val);    }}LL query(struct Node *root, LL L, LL R){    if(L == R){        if(root->add>=k) ans ++;        return 0;    }    LL midd=mid(root);    add(root->pL, root->L, midd, root->add);    add(root->pR, midd+1, root->R, root->add);    root->add=0;    if(R<=midd) return query(root->pL, L, R);    else if(L>midd) return query(root->pR, L, R);    else return query(root->pL, L, midd)+query(root->pR, midd+1, R);}int main() {    int t=1;    while(~scanf("%lld %lld %lld",&n,&m,&k)) {        cnt=0;        ans=0;        for(LL i=1; i<=n; i++) {            scanf("%lld",&a[i]);        }        sort(a+1,a+n+1);        build(tree,1,n);        LL first=2,second;        for(LL i=0; i<m; i++) {            scanf("%lld",&second);            LL firsttmp=lower_bound(a + 1, a + n + 1, first) - a;            LL secondtmp = upper_bound(a + 1, a + n + 1, second) - a - 1;            if(firsttmp>secondtmp) continue;//            if(secondtmp>n) secondtmp=n;            scanf("%lld",&first);            if(secondtmp < firsttmp) continue;            add(tree,firsttmp,secondtmp,1);            first++;        }        query(tree,1,n);        printf("Case %d: %lld\n",t++, ans);    }    return 0;}/*10 10 22 4 6 9 6 2 4 3 19 395 26 39 28 34 39 68 2Case 1: 69 8 23 7 2 9 8 4 3 2 15 26 39 28 49 210 646 510 3Case 2: 64 2 22 2 2 25 27 2Case 3: 0*/

还有一种方法,叫做差分,这适用于Q次更新,但是只有最后一次查询的状况,每次查询的时间复杂度是O(n).

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define MAX 100009#define inf 100000009int a[MAX],num[MAX],ans[MAX];int main(){    int n,m,k,t=1;    while(~scanf("%d %d %d",&n,&m,&k)){        memset(num,0,sizeof(num));        for(int i=1;i<=n;i++){            scanf("%d",&a[i]);        }        sort(a+1,a+n+1);        int first=2,second;        for(int i=0;i<m;i++){            scanf("%d",&second);            int firsttmp=lower_bound(a+1,a+n+1,first)-a;            int secondtmp=upper_bound(a+1,a+1+n,second)-a-1;            num[firsttmp]++;            num[secondtmp+1]--;            scanf("%d",&first);            first++;        }        int cnt=0;        ans[0]=0;        for(int i=1;i<=n;i++){            ans[i]=ans[i-1]+num[i];            if(ans[i]>=k) cnt++;        }        printf("Case %d: %d\n",t++, cnt);    }return 0;}



0 0
原创粉丝点击