线段树和单调队列--2018 UESTC Training for Data Structures F - 好吃不过饺子

题意:给n个对象 每个对象有坐标和能量两个变量 有c次查询 每次查询是关于输出每个坐标的能量值与坐标为当前坐标-len到当前坐标-1的所有对象的能量的关系(大于?小于)

相对比较水的一道题 有很多种方法可以做 一开始我是用纯线段树完成的 直接维护每个区间的最大最小和平均值 直接查询 但是错误以为他的平均值是整数向下取整算的 然而实际是用double+误差eps来确定与平均值关系 WA了很多次test 2 受思维定势影响吧:

AC代码:

#include <set>
#include <map>
#include <list>
#include <deque>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <iomanip>
#include <cstring>
#include <fstream>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define eps 1e-6
typedef long long ll;
const int maxn=100005;
const int inf=0x3f3f3f3f;

int a[maxn],b[maxn];
struct node
{
    ll sum;
    int mn,mx;
    int pos;
};
node tree[maxn<<2];

void pushup(int rt)
{
    tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
    tree[rt].mn=min(tree[rt<<1].mn,tree[rt<<1|1].mn);
    tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        tree[rt].sum=tree[rt].mn=tree[rt].mx=b[l];
        tree[rt].pos=a[l];
        tree[rt].sum=(ll)b[l];
        return ;
    }
    int m=l+(r-l)/2;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}
int bseek(int n,int c,int tp)
{
    int x=1,y=n;
    int m;
    while(x<y)
    {
        m=x+(y-x)/2;
        if(a[m]>=c) y=m;
        else x=m+1;
    }
    if(tp==1&&a[x]>c) x--;
    return x;
}
int mnquery(int le,int re,int l,int r,int rt)
{
    if(le<=l&&re>=r)
    {
        return tree[rt].mn;
    }
    int ret=inf;
    int m=l+(r-l)/2;
    if(le<=m) ret=min(ret,mnquery(le,re,l,m,rt<<1));
    if(re>m) ret=min(ret,mnquery(le,re,m+1,r,rt<<1|1));
    return ret;
}
int mxquery(int le,int re,int l,int r,int rt)
{
    if(le<=l&&re>=r)
    {
        return tree[rt].mx;
    }
    int ret=0;
    int m=l+(r-l)/2;
    if(le<=m) ret=max(ret,mxquery(le,re,l,m,rt<<1));
    if(re>m) ret=max(ret,mxquery(le,re,m+1,r,rt<<1|1));
    return ret;
}
ll smquery(int le,int re,int l,int r,int rt)
{
    if(le<=l&&re>=r)
    {
        return tree[rt].sum;
    }
    ll ret=0;
    int m=l+(r-l)/2;
    if(le<=m) ret+=smquery(le,re,l,m,rt<<1);
    if(re>m) ret+=smquery(le,re,m+1,r,rt<<1|1);
    return ret;
}
int main()
{
    int n,t;
    scanf("%d%d",&n,&t);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
    }
    build(1,n,1);
    while(t--)
    {
        char k[10],fuc[10];
        int len,le,re;
        scanf("%s",k);
        scanf("%s",fuc);
        scanf("%d",&len);
        if(strcmp(k,"gt")==0)
        {
            if(strcmp(fuc,"min")==0)
            {
                int ans=0;
                for(int i=1;i<=n;i++)
                {
                    le=bseek(n,a[i]-len,0);
                    re=bseek(n,a[i]-1,1);
                    if(re<1||re<le) continue;
                    int num=mnquery(le,re,1,n,1);
                    if(b[i]>num) ans++;
                }
                printf("%d\n",ans);
            }
            else if(strcmp(fuc,"max")==0)
            {
                int ans=0;
                for(int i=1;i<=n;i++)
                {
                    le=bseek(n,a[i]-len,0);
                    re=bseek(n,a[i]-1,1);
                    if(re<1||re<le) continue;
                    int num=mxquery(le,re,1,n,1);
                    if(b[i]>num) ans++;
                }
                printf("%d\n",ans);
            }
            else
            {
                int ans=0;
                for(int i=1;i<=n;i++)
                {
                    le=bseek(n,a[i]-len,0);
                    re=bseek(n,a[i]-1,1);
                    if(re<1||re<le) continue;
                    ll num=smquery(le,re,1,n,1);
                    double p=(double)num;
                    p/=(double)(re-le+1);
                    if((double)b[i]>p+eps) ans++;
                }
                printf("%d\n",ans);
            }
        }
        else if(strcmp(k,"lt")==0)
        {
            if(strcmp(fuc,"min")==0)
            {
                int ans=0;
                for(int i=1;i<=n;i++)
                {
                    le=bseek(n,a[i]-len,0);
                    re=bseek(n,a[i]-1,1);
                    if(re<1||re<le) continue;
                    int num=mnquery(le,re,1,n,1);
                    if(b[i]<num) ans++;
                }
                printf("%d\n",ans);
            }
            else if(strcmp(fuc,"max")==0)
            {
                int ans=0;
                for(int i=1;i<=n;i++)
                {
                    le=bseek(n,a[i]-len,0);
                    re=bseek(n,a[i]-1,1);
                    if(re<1||re<le) continue;
                    int num=mxquery(le,re,1,n,1);
                    if(b[i]<num) ans++;
                }
                printf("%d\n",ans);
            }
            else
            {
                int ans=0;
                for(int i=1;i<=n;i++)
                {
                    le=bseek(n,a[i]-len,0);
                    re=bseek(n,a[i]-1,1);
                    if(re<1||re<le) continue;
                    ll num=smquery(le,re,1,n,1);
                    double p=(double)num;
                    p/=(double)(re-le+1);
                    if((double)b[i]<p+eps) ans++;
                }
                printf("%d\n",ans);
            }
        }
    }
}

还有比较好的一种做法是用单调队列 因为每次维护都是维护以当前点-1位为终点的长度为某个定值的最大最小和平均值 这正是单调队列可以解决的经典问题 每次如果队头元素位置过小就从队头弹出 然后如果队尾的元素比当前元素大或小就弹出队尾 在队尾插入当前元素

总结一下 单调队列一般用来解决那些线性时间查询某个区间的最值问题 单调栈的话一般是询问以某一点为中心 向左或向右寻找第一个比他大或者小的元素的位置


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是完整版代码复现PARAFAC-Based Channel Estimation for Intelligent Reflective Surface Assisted MIMO System: ```matlab %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % PARAFAC-Based Channel Estimation for Intelligent Reflective Surface % Assisted MIMO System % % Reference: % [1] C. Huang, Y. Shi, Y. Huang, X. Yu, and Z. Ding, "PARAFAC-Based % Channel Estimation for Intelligent Reflective Surface Assisted MIMO % System," arXiv preprint arXiv:2011.07213, 2020. % % This code is written by Cheng Huang (huangcheng.uestc@hotmail.com). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% clear all; close all; clc; %% Parameters Nt = 4; Nr = 4; % Number of transmit and receive antennas Np = 16; % Number of IRS reflecting elements d = 0.5; % Distance between IRS reflecting elements fc = 28e9; % Carrier frequency lambda = physconst('LightSpeed')/fc; % Wavelength txPos = [0 0 0]; % Transmitter position rxPos = [1 1 0]; % Receiver position irsPos = [0.5 0.5 1]; % IRS position txArray = phased.URA(Nt,[0.5 0.5], 'ElementSpacing', lambda/2); % Transmitter antenna array rxArray = phased.URA(Nr,[0.5 0.5], 'ElementSpacing', lambda/2); % Receiver antenna array irsArray = phased.ConformalArray('ElementPosition', [0 0 0; repmat([d 0 0], Np-1, 1)], ... 'ElementNormal', [0 0 1; repmat([0 0 1], Np-1, 1)], 'Element', phased.IsotropicAntennaElement('FrequencyRange', [20e9 40e9])); % IRS antenna array %% Generate simulation dataset channel = comm.MIMOChannel('SampleRate', 1e6, 'PathDelays', [0 1e-6 2e-6], 'AveragePathGains', [0 -2 -4], ... 'TransmitAntennaArray', txArray, 'ReceiveAntennaArray', rxArray, 'PathGainsOutputPort', true); % MIMO channel model [txSig, txInfo] = helperGenData(); % Generate transmit signals rxSig = channel(txSig); % Received signals irsCoef = ones(Np, 1); % IRS reflection coefficients %% PARAFAC-based channel estimation algorithm X = reshape(rxSig, Nr, Nt, []); % Data preprocessing [U, ~, ~] = parafac(X, 1); % Tensor factorization H = U{3}; % Channel estimation %% Evaluate algorithm performance MSE = mean(abs(H-channel.PathGains).^2); BER = helperComputeBER(H, channel.PathGains); fprintf('MSE = %.4f, BER = %.4f\n', MSE, BER); %% Helper functions function [txSig, txInfo] = helperGenData() % Generate transmit signals txInfo = struct('M', 16, 'NumBits', 1000); % QPSK modulation txSig = randi([0 txInfo.M-1], txInfo.NumBits, 1); txSig = pskmod(txSig, txInfo.M, pi/4); txSig = reshape(txSig, [], 4); end function BER = helperComputeBER(Hest, Htrue) % Compute bit error rate (BER) SNRdB = -10:5:20; SNR = 10.^(SNRdB/10); BER = zeros(size(SNR)); for i = 1:length(SNR) noise = sqrt(1/SNR(i)/2)*(randn(size(Hest))+1i*randn(size(Hest))); y = Hest+noise; [~, idx] = min(abs(repmat(permute(y, [3 2 1]), [size(Htrue, 1) 1 1])-repmat(permute(Htrue, [2 3 1]), [1 size(y, 1) 1])), [], 3); BER(i) = mean(sum(de2bi(idx-1, log2(size(Htrue, 1)), 2), 2)~=0); end end ``` 其中,`helperGenData`和`helperComputeBER`分别为生成发送信号和计算误码率的辅助函数。运行代码后,会输出估计信道与真实信道之间的均方误差(MSE)和误码率(BER)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值