[补题]ACM-ICPC 2017 Asia Xi'an

G:

题意:查询[l,r]子区间异或的和

题解: 按位考虑,每一位统计奇数区间出现的次数算价值即可,线段树区间合并

#include <bits/stdc++.h>
#define ll long long
const ll mod=1e9+7;
const int MAXN=1e5+10;
using namespace std;
typedef struct node{
    int len,llen,rlen,sum;ll ans;
}node;
node d[21][MAXN*3+10005];
int dd[21][MAXN],a[MAXN];
void up(int x,int pos){
    d[pos][x].ans=(d[pos][x<<1].ans+d[pos][x<<1|1].ans)%mod;
    d[pos][x].ans+=d[pos][x<<1].rlen*(d[pos][x<<1|1].len-d[pos][x<<1|1].llen);
    d[pos][x].ans%=mod;
    d[pos][x].ans+=d[pos][x<<1|1].llen*(d[pos][x<<1].len-d[pos][x<<1].rlen);
    d[pos][x].ans%=mod;
    //d[pos][x].llen=d[pos][x<<1].llen+d[pos][x<<1|1].len+d[pos][x<<1].len-d[pos][x<<1].llen+d[pos][x<<1|1].llen;
    d[pos][x].llen=d[pos][x<<1].llen;d[pos][x].rlen=d[pos][x<<1|1].rlen;
    if(d[pos][x<<1].sum%2)d[pos][x].llen+=(d[pos][x<<1|1].len-d[pos][x<<1|1].llen);
    else d[pos][x].llen+=d[pos][x<<1|1].llen;
    if(d[pos][x<<1|1].sum%2)d[pos][x].rlen+=(d[pos][x<<1].len-d[pos][x<<1].rlen);
    else d[pos][x].rlen+=d[pos][x<<1].rlen;
    d[pos][x].len=d[pos][x<<1].len+d[pos][x<<1|1].len;
    d[pos][x].sum=d[pos][x<<1|1].sum+d[pos][x<<1].sum;
}
void built(int rt,int l,int r,int t){
    if(l==r){d[t][rt].sum=d[t][rt].ans=d[t][rt].llen=d[t][rt].rlen=dd[t][l];d[t][rt].len=1;return ;}
    int mid=(l+r)>>1;
    built(rt<<1,l,mid,t);
    built(rt<<1|1,mid+1,r,t);
    up(rt,t);
}
bool flag;node ttt;
int t1,t2;
node merge(node x,node y){
    x.ans+=y.ans;
    x.ans+=x.rlen*(y.len-y.llen);
    x.ans+=(x.len-x.rlen)*y.llen;
    t1=x.llen;t2=y.rlen;
    if(x.sum%2)t1+=(y.len-y.llen);
    else t1+=y.llen;
    if(y.sum%2)t2+=(x.len-x.rlen);
    else t2+=x.rlen;
    x.llen=t1;x.rlen=t2;
    x.len+=y.len;x.sum+=y.sum;
    return x;
}
void querty(int rt,int l,int r,int ql,int qr,int t){
    if(ql<=l&&r<=qr){
        if(!flag)ttt=d[t][rt],flag=1;
        else ttt=merge(ttt,d[t][rt]);
        return ;
    }
    int mid=(l+r)>>1;
    if(ql<=mid)querty(rt<<1,l,mid,ql,qr,t);
    if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr,t);
}
int main(){
    int _;scanf("%d",&_);
    while(_--){
        int n,q;scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=0;i<=20;i++){
            for(int j=1;j<=n;j++){
                if(a[j]&(1<<i))dd[i][j]=1;
                else dd[i][j]=0;
            }
        }
        for(int i=0;i<=20;i++)built(1,1,n,i);
        int l,r;ll ans=0;
        for(int i=1;i<=q;i++){
            scanf("%d%d",&l,&r);ans=0;
            for(int j=0;j<=20;j++){
                flag=0;querty(1,1,n,l,r,j);
                ans=(ans+(ttt.ans%mod)*(1<<j)%mod)%mod;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

K:

题解:查询[l,r]区间里面的男生和女生是否在满足要求的情况下进行匹配,可以通过线段树+双指针预处理出每个位置最小满足的右端点即可(icpc官网上没有数据 计蒜课上的数据也是假的,对拍了一晚上大数据感觉没啥问题)

#include <bits/stdc++.h>
const int MAXN=2e5+10;
using namespace std;
int mn[MAXN<<2],flag[MAXN<<2];
void push(int x){
    if(flag[x]){
        mn[x<<1]+=flag[x];
        mn[x<<1|1]+=flag[x];
        flag[x<<1]+=flag[x];
        flag[x<<1|1]+=flag[x];
        flag[x]=0;
    }
}
void up(int x){mn[x]=min(mn[x<<1],mn[x<<1|1]);return ;}
void built(int rt,int l,int r){
    if(l==r){mn[rt]=-1*l,flag[rt]=0;return ;}
    int mid=(l+r)>>1;
    built(rt<<1,l,mid);
    built(rt<<1|1,mid+1,r);
    up(rt);flag[rt]=0;
}
void update(int rt,int l,int r,int ql,int qr,int t){
    if(ql<=l&&r<=qr){mn[rt]+=t;flag[rt]+=t;return ;}
    push(rt);
    int mid=(l+r)>>1;
    if(ql<=mid)update(rt<<1,l,mid,ql,qr,t);
    if(qr>mid)update(rt<<1|1,mid+1,r,ql,qr,t);
    up(rt);
}
vector<int>vec;
int a[MAXN],ans[MAXN];
int main(){
    int _;scanf("%d",&_);
    while(_--){
        int n,m,k,t;scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)scanf("%d",&t),vec.push_back(t);
        sort(vec.begin(),vec.end());
        for(int i=1;i<=m;i++)scanf("%d",&a[i]);
        for(int i=1;i<=m;i++) a[i]=lower_bound(vec.begin(),vec.end(),k-a[i])-vec.begin()+1,ans[i]=m+1;
        for(int i=m+1;i<=max(n,m);i++) a[i]=n+1;
       // for(int i=1;i<=m;i++)cout<<a[i]<<" ";
        //cout<<endl;
        built(1,1,n);
        for(int i=1;i<=n;i++){
            if(a[i]>n)continue;
            update(1,1,n,a[i],n,1);
        }
        int l=1;int r=n;
        while(r<=m){
            while(r<=m&&mn[1]<0){
                r++;
                if(a[r]<=n)update(1,1,n,a[r],n,1);
            }
            if(r>m)break;
            ans[l]=r;
            //cout<<l<<" "<<ans[l]<<endl;
            if(a[l]<=n)update(1,1,n,a[l],n,-1);
            l++;
        }
        int q;scanf("%d",&q);
        for(int i=1;i<=q;i++){
            scanf("%d%d",&l,&r);
            if(ans[l]<=r)puts("1");
            else puts("0");
        }
        vec.clear();
    }
    return 0;
}

  

[补题]ACM-ICPC 2017 Asia Xi'an

原文地址:https://www.cnblogs.com/wang9897/p/9094854.html

时间: 2024-10-11 11:42:47

[补题]ACM-ICPC 2017 Asia Xi'an的相关文章

UPC5431/acm icpc 2017 Tehran Column Addition

题目链接:http://exam.upc.edu.cn/problem.php?cid=1326&pid=7 题意:给你一个可能存在错误的加法等式,问最少删除多少列能使等式成立. eg: 思考:如果某一列已经成立,如上图的1+4=5,他一定可以加到前面最长的成立的等式上,类似于最长上升子序列,不过要n^2扫. 做题时WA了几发,因为没考虑到等式的最高位不能有进位,以及可能某一列一开始没有进位,但是后来由于前面低位的进位导致了自己的进位(这种情况只会出现在初始和为9,低位又进一的情况). 1 #i

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ

hdu6206 Apple 2017 ACM/ICPC Asia Regional Qingdao Online

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6206 题目: Apple Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 530    Accepted Submission(s): 172 Problem Description Apple is Taotao's favouri

hdu 5008(2014 ACM/ICPC Asia Regional Xi&#39;an Online ) Boring String Problem(后缀数组&amp;二分)

Boring String Problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 219    Accepted Submission(s): 45 Problem Description In this problem, you are given a string s and q queries. For each que

2014 ACM/ICPC Asia Regional Xi&#39;an Online(HDU 5007 ~ HDU 5017)

题目链接 A题:(字符串查找,水题) 题意 :输入字符串,如果字符串中包含“ Apple”, “iPhone”, “iPod”, “iPad” 就输出 “MAI MAI MAI!”,如果出现 “Sony” 就输出“SONY DAFA IS GOOD!” ,大小写敏感. 思路 : 字符串查找,水题. 1 #include <string.h> 2 #include <stdio.h> 3 #include <iostream> 4 5 using namespace st

2014 ACM/ICPC Asia Regional Xi&#39;an Online 233 Matrix,hdu 5015

比赛的时候若是这题过了就进前50 刚开始的时候大家的思路都以为是找规律的题目,于是再推公式,此外还发现类似于杨辉三角.于是又去套杨辉三角的通项去求. 于是TLE了无数次.(每次取范围的最大值也要3s多). 对于明显的矩阵样子,其实可以转化为矩阵的运算,每一行的转移.就是对一个转移矩阵的幂运算.然后再用快速矩阵幂即可. A: 10 0 0 1 10 1 0 1 10 1 1 1 0  0  0 1 B: 23 0 0 3 C=A^M  *B,ans=C[N] 教训:对于时间限制,即便是最大数据也要

2014 ACM/ICPC Asia Regional Xi&#39;an Online

03 hdu5009 状态转移方程很好想,dp[i] = min(dp[j]+o[j~i]^2,dp[i]) ,o[j~i]表示从j到i颜色的种数. 普通的O(n*n)是会超时的,可以想到o[]最大为sqrt(n),问题是怎么快速找到从i开始往前2种颜色.三种.四种...o[]种的位置. 离散化之后,可以边走边记录某个数最后一个出现的位置,初始为-1,而所要求的位置就等于 if(last[a[i]]==-1) 该数没有出现过,num[i][1] = i,num[i][j+1] = num[i-1

HDU 5009 Paint Pearls _(:зゝ∠)_2014 ACM/ICPC Asia Regional Xi&#39;an Online

呵呵 #include <cstdio> #include <algorithm> #include <iostream> #include <cstring> typedef long long ll; using namespace std; const int N = 5 * 10000 + 5; int xval[N], dep; int n, a[N], pre[N]; ll d[N]; int pos[300], dd; void work()

HDU 5014 Number Sequence 贪心 2014 ACM/ICPC Asia Regional Xi&#39;an Online

尽可能凑2^x-1 #include <cstdio> #include <cstring> const int N = 100005; int a[N], p[N]; int init(int x) { int cnt = 0; while(x > 1) { x /= 2; cnt ++; } return cnt + 1; } int main() { int n; while(~scanf("%d", &n)){ for(int i = 0;