AcWing模板题(二)

子矩阵的和(二维前缀和)

子矩阵的和

#include <bits/stdc++.h>
using namespace std;

const int N=1010;
int n,m,q;
int a[N][N],sum[N][N];

int main(){
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            sum[i][j]=a[i][j]+sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
        }
    }
    
    while(q--){
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        int ans=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
        cout<<ans<<endl;
    }
    
    return 0;
}

差分

在 [ l , r ] 之间每个数加上 c ,重复 m 次操作

797. 差分 - AcWing题库

//a[i]=b[i]+b[i-1]
#include <bits/stdc++.h>
using namespace std;

const int N=100010;
int a[N],b[N];

void insert(int l,int r,int c){
    b[l]+=c;
    b[r+1]-=c;
}

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        insert(i,i,a[i]);
    }
    
    while(m--){
        int l,r,c;
        cin>>l>>r>>c;
        insert(l,r,c); 
    }
    
    for(int i=1;i<=n;i++){
        b[i]+=b[i-1];
        cout<<b[i]<<" ";
    }
    
    return 0;
}

差分矩阵

在子矩阵中的每个元素上加上 c , (x1,y1) 和 (x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。

重复 q 次操作。

差分矩阵

#include <bits/stdc++.h>
using namespace std;

const int N=1010;
int n,m,q;
int a[N][N],b[N][N];

void insert(int x1,int y1,int x2,int y2,int c){
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;
}

int main(){
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            insert(i,j,i,j,a[i][j]);
        }
    }
    
    while(q--){
        int x1,y1,x2,y2,c;
        cin>>x1>>y1>>x2>>y2>>c;
        insert(x1,y1,x2,y2,c);
    }
    
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
            cout<<b[i][j]<<" ";
        }
        cout<<endl;
    }
    
    return 0;
    
}

最长连续不重复子序列

最长连续不重复子序列

# include <iostream>
using namespace std;

const int N = 100010;
int a[N], cnt[N];

int main()
{
    int n, ans = 0;
    cin >> n;

    for (int i = 0, j = 0; i < n; i++)
    {
        cin >> a[i];
        cnt[a[i]]++;
        while (cnt[a[i]] > 1)  cnt[a[j++]]--; 
        ans = max(ans, i - j + 1) ;
    }
    cout << ans;

    return 0;
}

数组元素的目标和(二分查找)

数组元素的目标和

#include <bits/stdc++.h>
using namespace std;

const int N=100010;
typedef long long ll;
ll n,m,x;
ll a[N],b[N];

int main(){
    cin>>n>>m>>x;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];
    
    for(int i=1;i<=n;i++){
        int pos = lower_bound(b,b+m,x-a[i]) - b;
        if(b[pos]+a[i] == x) {
            cout<<i-1<<" "<<pos-1<<endl;
            break;
        }
        else continue;
    }
    
    return 0;
}

区间和(离散化)

在 x 位置上插入 c , n 次后询问 m 次 [ l , r ] 之间数的和

离散化

#include <bits/stdc++.h>
using namespace std;

typedef pair <int,int> PII;
const int N=300010;
int a[N],s[N];

vector <int> alls;
vector <PII> add,query;

int find(int x){
	int l=0,r=alls.size();
	
	while(l<r){
		int mid=l+r>>1;
		if(alls[mid]>=x) r=mid;
		else l=mid+1;
	}
	return l+1;
}

int main(){
	int n,m;
	cin>>n>>m;
	
	for(int i=0;i<n;i++){
		int x,c;
		cin>>x>>c;
		
		add.push_back({x,c});
		alls.push_back(x);
	}
	
	for(int i=0;i<m;i++){
		int l,r;
		cin>>l>>r;
		
		query.push_back({l,r});
		alls.push_back(l);
		alls.push_back(r);
	}
	
	sort(alls.begin(),alls.end());
	alls.erase(unique(alls.begin(),alls.end()),alls.end());
	
	for(auto item:add){
		int x=find(item.first);
		a[x]+=item.second;
	}
	
	for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];
	
	for(auto item:query){
		int l=find(item.first);
		int r=find(item.second);
		cout<<s[r]-s[l-1]<<endl;
	}
	
	return 0;
}

区间合并(贪心)

按左端点从小到大排序

区间合并

#include <bits/stdc++.h>
using namespace std;

const int N=100010;

typedef long long ll;
struct node {
    ll l;
    ll r;
}a[N];

bool cmp(node a,node b){
    return a.l<b.l;
}

int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i].l>>a[i].r;
    }
    
    sort(a,a+n,cmp);
    
    int ans=1;
    ll temp=a[0].r;
    for(int i=1;i<n;i++){
        if(a[i].l>temp){
            ans++;
            temp=a[i].r;
        }
        else temp=max(temp,a[i].r);
    }
    
    cout<<ans<<endl;
    
    return 0;
}

单调栈

输出 N 个整数,其中第 i 个数表示第 i 个数的左边第一个比它小的数,如果不存在则输出 −1。

单调栈

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;
int stk[N],t;

int main(){
    int n;
    cin>>n;
    
    while(n--){
        int x;
        cin>>x;
        
        while(t>0&&stk[t]>=x) t--;
        
        if(!t) cout<<"-1"<<" ";
        else cout<<stk[t]<<" ";
        
        stk[++t] = x;
    }
    
    return 0;
}

KMP

KMP字符串

#include <bits/stdc++.h>
using namespace std;

const int N = 1000010; //N为模式串长度,M匹配串长度

int n, m;
int ne[N]; //next[]数组,避免和头文件next冲突
char s[N], p[N];  //s为模式串, p为匹配串

int main()
{
    cin >> m >> p+1 >> n >> s+1;  //下标从1开始

    //求next[]数组
    for(int i = 2, j = 0; i <= m; i++)
    {
        while(j && p[i] != p[j+1]) j = ne[j];
        if(p[i] == p[j+1]) j++;
        ne[i] = j;
    }
    //匹配操作
    for(int i = 1, j = 0; i <= n; i++)
    {
        while(j && s[i] != p[j+1]) j = ne[j];
        if(s[i] == p[j+1]) j++;
        if(j == m) 
        {
            cout<<i-m<<" ";
            j = ne[j];            //再次继续匹配
        }
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是acwing模板线段树的示例代码: ```cpp const int N = 100010; int n, m; int a[N]; struct Node { int l, r; int v, lazy; } tree[N * 4]; void pushup(int x) { tree[x].v = tree[x * 2].v + tree[x * 2 + 1].v; } void pushdown(int x) { if (tree[x].lazy) { int l = tree[x].l, r = tree[x].r; int mid = (l + r) >> 1; tree[x * 2].v += tree[x].lazy * (mid - l + 1); tree[x * 2 + 1].v += tree[x].lazy * (r - mid); tree[x * 2].lazy += tree[x].lazy; tree[x * 2 + 1].lazy += tree[x].lazy; tree[x].lazy = 0; } } void build(int x, int l, int r) { tree[x].l = l, tree[x].r = r; if (l == r) { tree[x].v = a[l]; return; } int mid = (l + r) >> 1; build(x * 2 l, mid); build(x * 2 + 1, mid +1, r); pushup(x); } void modify(int x, int l, int r, int val) { if (tree[x].l >= l && tree[x].r <= r) { tree[x].v += val * (tree[x].r - tree[x].l + 1); tree[x].lazy += val; return; } pushdown(x); int mid = (tree[x].l + tree[x].r) >> 1; if (l <= mid) modify(x * 2, l, r, val); if (r > mid) modify(x * 2 + 1, l, r, val); pushup(x); } int query(int x, int l, int r) { if (tree[x].l >= l && tree[x].r <= r) { return tree[x].v; } pushdown(x); int mid = (tree[x].l + tree[x].r) >> 1; int sum = 0; if (l <= mid) sum += query(x * 2, l, r); if (r > mid) sum += query(x * 2 + 1, l, r); return sum; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; } build(1, 1, n); while (m--) { int op, l, r, val; cin >> op; if (op == 1) { cin >> l >> r >> val; modify(1, l, r, val); } else if (op == 2) { cin >> l >> r; cout << query(1, l, r) << endl; } } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值