uva12003 - Array Transformer 分块结构

Write a program to transform an array A[1], A[2], . . . , A[n] according to m instructions. Each instruction(L, R, v, p) means: First, calculate how many numbers from A[L] to A[R] (inclusive) are strictly lessthan v, call this answer k. Then, change the value of A[p] to u ∗ k/(R − L + 1), here we use integerdivision (i.e. ignoring fractional part).InputThe first line of input contains three integer n, m, u (1 ≤ n ≤ 300, 000, 1 ≤ m ≤ 50, 000, 1 ≤ u ≤1, 000, 000, 000). Each of the next n lines contains an integer A[i] (1 ≤ A[i] ≤ u). Each of the nextm lines contains an instruction consisting of four integers L, R, v, p (1 ≤ L ≤ R ≤ n, 1 ≤ v ≤ u,1 ≤ p ≤ n).OutputPrint n lines, one for each integer, the final array.Sample Input10 1 11123456789102 8 6 10Sample Output1234567896Explanation: There is only one instruction: L = 2, R = 8, v = 6, p = 10. There are 4 numbers(2,3,4,5) less than 6, so k = 4. The new number in A[10] is 11 ∗ 4/(8 − 2 + 1) = 44/7 = 6.

  输入N(1<=N<=300000),M(1<=M<=50000),U(1<=U<=10^9),接下来输入数组a(N个数),M次操作,每次操作输入L,R,V,P,计算出[L,R]区间内小于V的数的个数k,把A[P]修改为U*k/(R-L+1)。最后输出M次操作后的数组。

  把数组分块,每块大小在根号N附近(这样比较快),对每块排序,这样每次询问L,R的时候在L,R所在的块进行暴力查找,L,R之间的块用二分查找。修改的时候不光要修改原数组,还要修改分块数组,找到P所在的块,然后找到要修改的值所在的位置,把这个位置替换为新值,再维护块内的顺序。找L,R所在块的位置很好找,因为是按顺序分的,所以直接用位置除以块大小就是块编号。

  分块法其实也就是划分成小范围的暴力,这里如果块大小取根号N的话,复杂度O(M*√N*log√N), 白书上说分块法非常有用,很多用伸展树或树套树能解决的问题用分块法。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;

const int MAXN=300010;
const int SIZE=4096;
const int INF=0x3f3f3f3f;

int N,M,U,L,R,V,P;
int a[MAXN],block[MAXN/SIZE+1][SIZE];

int query(int l,int r,int v){
    int lb=l/SIZE,rb=r/SIZE;
    int ret=0;
    if(lb==rb){
        for(int i=l;i<=r;i++) if(a[i]<v) ret++;
    }
    else{
        for(int i=l;i<(lb+1)*SIZE;i++) if(a[i]<v) ret++;
        for(int i=rb*SIZE;i<=r;i++) if(a[i]<v) ret++;
        for(int i=lb+1;i<rb;i++) ret+=lower_bound(block[i],block[i]+SIZE,v)-block[i];
    }
    return ret;
}

void change(int p,int x){
    if(a[p]==x) return;
    int old=a[p],pos=0,*b=block[p/SIZE];
    a[p]=x;
    while(b[pos]<old) pos++;
    b[pos]=x;
    if(x>old){
        while(pos<SIZE-1&&b[pos]>b[pos+1]){
            swap(b[pos+1],b[pos]);
            pos++;
        }
    }
    else{
        while(pos>0&&b[pos]<b[pos-1]){
            swap(b[pos-1],b[pos]);
            pos--;
        }
    }
}

int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d%d%d",&N,&M,&U)!=EOF){
        int b=0,j=0;
        for(int i=0;i<N;i++){
            scanf("%d",&a[i]);
            block[b][j]=a[i];
            if(++j==SIZE){
                b++;
                j=0;
            }
        }
        for(int i=0;i<b;i++) sort(block[i],block[i]+SIZE);
        if(j) sort(block[b],block[b]+j);
        while(M--){
            scanf("%d%d%d%d",&L,&R,&V,&P);
            L--;
            R--;
            P--;
            int k=query(L,R,V);
            change(P,(LL)U*k/(R-L+1));
        }
        for(int i=0;i<N;i++) printf("%d\n",a[i]);
    }
    return 0;
}


### Swin-Transformer 模块网络结构图及架构可视化 #### 网络结构概述 Swin-Transformer 是一种基于窗口的分层 Transformer 架构,专为计算机视觉任务设计[^1]。其核心思想是通过递归地将特征图划分为不重叠的局部窗口,并在每个窗口内执行自注意力机制,从而实现高效的特征提取和建模。 Swin-Transformer 的主要组成部分包括: - **Patch Partitioning(Patch 分区)**:将输入图像划分为固定大小的非重叠 Patch,并通过线性嵌入将其转换为特征向量。 - **Swin Transformer Blocks**:包含两种类型的自注意力机制——W-MSA(Window-based Multi-head Self-Attention)和 SW-MSA(Shifted Window-based Multi-head Self-Attention),用于捕获局部和全局特征。 - **Patch Merging(Patch 合并)**:在每个 Stage 结束时对特征图进行下采样,减少空间分辨率并增加通道维度。 - **MLP Layers(多层感知机层)**:用于进一步处理自注意力机制输出的特征。 以下是 Swin-Transformer 的完整网络结构图及其详细说明。 --- #### 完整网络结构图 ```plaintext Input Image -> Patch Partitioning -> Stage 1 -> Stage 2 -> ... -> Stage N -> Output ``` 具体绘制顺序如下: 1. **输入层**: - 输入图像经过 Patch Partitioning 层,将图像划分为固定大小的 Patch 并通过线性嵌入层将其转换为特征向量。 2. **多个 Stage**: - 每个 Stage 包含以下子模块: - **Patch Merging**:对特征图进行下采样,减少空间分辨率并增加通道维度。 - **Swin Transformer Blocks**:堆叠多个 Swin Transformer Block,每个 Block 包含以下部分: - **Layer Normalization**:对输入特征进行归一化处理。 - **W-MSA 或 SW-MSA**:交替使用 W-MSA 和 SW-MSA,分别用于捕获局部和全局特征。 - **MLP Layer**:通过两层全连接网络进一步处理特征。 - **Residual Connections**:通过残差连接增强模型的训练稳定性。 3. **输出层**: - 最终输出特征图,可用于分类、检测或其他任务。 --- #### 网络结构图示例 以下是 Swin-Transformer 的网络结构图示例,以 Markdown 格式表示: ```plaintext Input Image (HxWxC) ↓ Patch Partitioning (Nx(embed_dim)) ↓ Stage 1: - Patch Merging - Swin Transformer Blocks (W-MSA, MLP) ↓ Stage 2: - Patch Merging - Swin Transformer Blocks (SW-MSA, MLP) ↓ ... ↓ Stage N: - Patch Merging - Swin Transformer Blocks (W-MSA, MLP) ↓ Output Features ``` --- #### 可视化工具 为了更好地理解 Swin-Transformer 的特征提取过程,可以使用 Grad-CAM 工具对模型的中间特征进行可视化。PyTorch-Grad-CAM 提供了对 Swin-Transformer 等模型的可视化支持,适用于图像分类、目标检测和分割等任务[^1]。 安装 PyTorch-Grad-CAM 的命令如下: ```bash pip install grad-cam ``` 代码示例: ```python from pytorch_grad_cam import GradCAM from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget from pytorch_grad_cam.utils.image import show_cam_on_image # 加载预训练模型 model = torch.hub.load('microsoft/Swin-Transformer', 'swin_tiny_patch4_window7_224', pretrained=True) # 初始化 Grad-CAM target_layers = [model.layers[-1].blocks[-1].norm1] # 目标层 cam = GradCAM(model=model, target_layers=target_layers) # 输入图像 input_tensor = ... # 输入张量 targets = [ClassifierOutputTarget(class_id)] # 类别目标 # 生成热力图 grayscale_cam = cam(input_tensor=input_tensor, targets=targets) visualization = show_cam_on_image(image, grayscale_cam, use_rgb=True) ``` --- #### 修改配置文件以适配自定义数据集 对于 Swin-Transformer 在目标检测或分割任务中的应用,可以通过修改配置文件来适配自定义数据集。例如,在 Mask R-CNN 中使用 Swin-Transformer 作为主干网络时,需要调整类别数和其他相关参数[^2]。 修改步骤如下: 1. 修改 `configs_base_models\mask_rcnn_swin_fpn.py` 文件中的 `num_classes` 参数,设置为目标类别的数量。 2. 使用 `modify.py` 脚本更新预训练模型的类别数: ```bash python modify.py --weights mask_rcnn_swin_tiny_patch4_window7_1x.pth --num_class 4 --output model_new.pth ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值