hdu5212 Code 莫队算法

本文介绍如何使用莫队算法解决特定的区间查询问题,并提供了一段详细的C++代码实现。通过将一个复杂的区间查询拆分为四个子问题,可以有效地降低整体的时间复杂度。
这道题需要一些莫队算法的知识
定义记号f(A,B)表示询问区间A,B时的答案
用记号+表示集合的并
利用莫队算法我们可以计算出任意f(A,A)的值
不妨假设A=[l1,r1],B=[l2,r2],C=[r1+1,l21]
容易知道f(A,B)=f(A+B+C,A+B+C)+f(C,C)f(A+C,A+C)f(C+B,C+B)
因此一个询问被拆成四个可以用莫队算法做的询问
总的时间复杂度为O(msqrt(n))
(以上是官方题解)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
typedef long long LL;
const int N = 30000*4 + 10;


int pos[N];
struct pp{
    int l,r,id;
    int ans;
}p[N];
int cmp(pp a,pp b){
    if(pos[a.l]==pos[b.l]) return a.r < b.r;
    return a.l < b.l;
}
int cmp2(pp a,pp b){
    return a.id < b.id;
}


struct que{
    int l1,l2,r1,r2;
}q[N];
int block,n,k,m,num;
int a[N],cnt[N],answer;
LL x;


map<LL,int> mm;


void update(int x,int v){
    int val = k - a[x];
    if(val <= 0) return ;
    answer += cnt[val]*v;
    cnt[a[x]] += v;
}


void solve(){
    int l,r;
    answer = 0;
    for(int i=1,l=1,r=0;i<=num;i++){//按块进行更新
        for(;r<p[i].r;r++)
            update(r+1,1);
        for(;r>p[i].r;r--)
            update(r,-1);
        for(;l<p[i].l;l++)
            update(l,-1);
        for(;l>p[i].l;l--)
            update(l-1,1);
        p[i].ans = answer;
    }
}


int main(){
    while(scanf("%d",&n)!=EOF){
        mm.clear();
        num = 0;
        block = (int)sqrt(n)+1;
        for(int i=1;i<=n;i++) pos[i] = i/block + 1;
        scanf("%d",&k);
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int l1,l2,r1,r2;
            scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
            q[i].l1 = l1 , q[i].r1 = r1 , q[i].l2 = l2 , q[i].r2 = r2;
            p[++num].l = l1 , p[num].r = l2-1 ;
            x = l1*40000+(l2-1);
            mm[x] = num;
            p[num].id = num;


            p[++num].l = r1+1 , p[num].r = r2 ;
            x = (r1+1)*40000+r2;
            mm[x] = num;
            p[num].id = num;


            if(l2-1 >= r1+1){
                p[++num].l = r1+1 , p[num].r = l2-1 ;
                x = (r1+1)*40000+(l2-1);
                mm[x] = num;
                p[num].id = num;
            }


            p[++num].l = l1 , p[num].r = r2 ;
            x = l1*40000+r2;
            mm[x] = num;
            p[num].id = num;
        }
        sort(p+1,p+1+num,cmp);
        solve();
        sort(p+1,p+1+num,cmp2);
        for(int i=1;i<=m;i++){
            int l1,l2,r1,r2;
            l1 = q[i].l1 , l2 = q[i].l2 , r1 = q[i].r1 , r2 = q[i].r2 ;
            LL ans = 0;


            x = l1*40000+r2;
            ans += p[mm[x]].ans;


            if(l2-1>=r1+1){
                x = (r1+1)*40000+(l2-1);
                ans += p[mm[x]].ans;
            }




            x = (r1+1)*40000+r2;
            ans -= p[mm[x]].ans;


            x = l1*40000+(l2-1);
            ans -= p[mm[x]].ans;


            printf("%lld\n",ans);
        }
    }
    return 0;
}
要解决被HDU WAF(Web应用防火墙)拒绝的问题并调整代码,可从以下几个方面着手: ### 网络访问规范 - **IP限制**:HDU WAF可能因IP存在异常访问行为而拒绝访问。检查IP是否被列入黑名单,若因频繁请求被临时封禁,可等待封禁时间结束或联系HDU相关技术支持人员说明情况,请求解封。 - **请求频率**:过度频繁的请求会触发WAF的防护机制。调整代码中的请求频率,添加适当的延迟。以下是Python中使用`time.sleep()`函数添加延迟的示例: ```python import time import requests for i in range(10): response = requests.get('http://acm.hdu.edu.cn') print(response.text) time.sleep(1) # 每次请求间隔1秒 ``` ### 代码合规性 - **请求头设置**:确保代码中的请求头信息符合正常浏览器的请求头格式。部分WAF会根据请求头信息判断请求是否正常。以下是Python中设置请求头的示例: ```python import requests headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} response = requests.get('http://acm.hdu.edu.cn', headers=headers) print(response.text) ``` - **请求参数**:检查代码中发送的请求参数是否包含恶意字符或异常内容。确保参数符合题目要求和网站规定。 ### 代码逻辑与题目要求 - **理解题目意思**:仔细阅读题目描述,确保代码逻辑符合题目要求。如VJ的题有很多格式要求,多打一个空格、没换行系统就会评测为presentation error,所以要在代码中严格遵循题目要求的输出格式[^2]。 - **优化算法复杂度**:若代码运行时间过长或占用资源过多,可能会被WAF视为异常请求。对代码中的算法进行优化,降低时间和空间复杂度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值