zoukankan      html  css  js  c++  java
  • Pudding Monsters CodeForces

    大意: n*n棋盘, n个点有怪兽, 求有多少边长为k的正方形内恰好有k只怪兽, 输出k=1,...,n时的答案和.

    等价于给定n排列, 对于任意一个长为$k$的区间, 若最大值最小值的差恰好为k, 则产生1贡献, 求贡献和.考虑分治, 问题就转化为如何$O(n)$求出跨越$mid$的贡献, 可以讨论最大值最小值的位置, 双指针求出.

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #define REP(i,a,n) for(int i=a;i<=n;++i)
    #define PER(i,a,n) for(int i=n;i>=a;--i)
    using namespace std;
    typedef long long ll;
    
    const int N = 1e6+10;
    int n, a[N], mx[N], mi[N];
    int ff[N<<1], *f=ff+N;
    ll ans;
    void solve(int l, int r) {
    	if (l==r) return ++ans,void();
    	int mid = l+r>>1;
    	solve(l,mid),solve(mid+1,r);
    	mx[mid]=mi[mid]=a[mid];
    	mx[mid+1]=mi[mid+1]=a[mid+1];
    	REP(i,mid+2,r) mx[i]=max(mx[i-1],a[i]),mi[i]=min(mi[i-1],a[i]);
    	PER(i,l,mid-1) mx[i]=max(mx[i+1],a[i]),mi[i]=min(mi[i+1],a[i]);
    	int L = mid, R = mid;
    	REP(i,mid+1,r) {
    		int j=i-mx[i]+mi[i];
    		if (l<=j&&j<=mid&&mx[j]<mx[i]&&mi[j]>mi[i]) ++ans;
    		while (L>=l&&mx[L]<mx[i]) ++f[mi[L]-L],--L;
    		while (R>L&&mi[R]>mi[i]) --f[mi[R]-R],--R;
    		ans += f[mx[i]-i];
    	}
    	while (R!=L) --f[mi[R]-R],--R;
    	L = R = mid+1;
    	PER(i,l,mid) {
    		int j=mx[i]-mi[i]+i;
    		if (mid+1<=j&&j<=r&&mx[j]<mx[i]&&mi[j]>mi[i]) ++ans;
    		while (R<=r&&mx[R]<mx[i]) ++f[mi[R]+R],++R;
    		while (L<R&&mi[L]>mi[i]) --f[mi[L]+L],++L;
    		ans += f[mx[i]+i];
    	}
    	while (L!=R) --f[mi[L]+L],++L;
    }
    
    int main() {
    	scanf("%d", &n);
    	REP(i,1,n) {
    		int x, y;
    		scanf("%d%d", &x, &y);
    		a[x] = y;
    	}
    	solve(1,n);
    	printf("%lld
    ", ans);
    }
    
  • 相关阅读:
    微信·小程序开发工具安装指南及注意事项
    测试
    PC上面的蓝牙的通信(C#)
    关于图片在div中居中问题
    JSONP---跨域请求问题
    关于position的用法
    APICloud自学笔记总结1
    前端html5
    关于图片自适应div大小问题
    亲身经历——大体量公司能为程序员的生涯带来什么帮助?
  • 原文地址:https://www.cnblogs.com/uid001/p/10685231.html
Copyright © 2011-2022 走看看