【CodeChef AUG16 T4】Chef and His Garden
来源:互联网 发布:win7隐藏网络连接 编辑:程序博客网 时间:2024/05/17 04:56
这种情况很水,枚举每一个区间即可,当然在这个枚举的过程中要直接计算出区间最大值,
用线段树是过不掉的。。。
即将题目转化为求
那么我们来考虑每个数
我们知道当且仅当
于是很容易想到的一个思路就是分治
对于
然后累加上它对答案的贡献
这样接下来的所有情况区间都不应包含点
于是我们可以将区间劈成两半,而后分别运行
此情况得解
我们会发现这时我们可以把对于一个数
在
然而这样每层的是
然而我们可以发现每次只劈成两个区间
于是我们可以先解决小的那个区间,然后将其
然后再解决大的那个区间,不将其
最后将小区间的
这样由于每次加减的都是较小的那个区间,复杂度较小
于是解决了这个情况的问题,复杂度为
那么这个复杂度证明证明呢?
我们发现,对于每个区间,在它劈成两半时会减去一个点,
也就是说,每多出一个区间就会少去一个点,
所以对于每个区间,它的儿子的个数等于区间长度
所以我没每次保留的那个大区间一定是原区间的重儿子
所以这个算法的复杂度证明与
可能有重复情况需要特判,这档我没写。。
绕了这么大一个圈,然后我们再来解决这个神奇的原题
对于
经过上一档的解决过程,我们发现,
于是自然而然的想到,将这个
那么这时候这么解呢?
有这样一个思路:我们根据左边的每个数的第一关键字找出他能变成的所有儿子和所有父亲
如:
我们将这些数全部
当然对于它的所有第一关键字父亲
然后对于右边的每一个数,按照第二关键字走向它的父亲和儿子,累加上所有答案
比如
它可以找到它的第二关键字父亲
如果是找儿子,那就累加上那个数的
即如下所示,对于任意两个数,只要存在包含关系,按照这样运动肯定会相撞
当然优化和之前
值得注意的是,这种情况下左右两区间中有数字相等的话这两个数字的答案就会被重复计算
于是还要存一个
于是复杂度
代码如下:
#include<bits/stdc++.h>using namespace std;#define M 100005#define N 145#define ll long longint a[M],cnt[3][N*N],n;ll ans;vector<int>son[N],fa[N];struct node{ int mx,id; bool operator <(const node &A)const{ return mx<A.mx; }};struct Tree{//线段树求取区间最值 node tree[M<<2]; void up(int p){ tree[p]=max(tree[p<<1],tree[p<<1|1]); } void build(int p=1,int l=1,int r=n){ if(l==r){ tree[p]=(node){a[l],l}; return; } int mid=l+r>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); up(p); } node query(int L,int R,int p=1,int l=1,int r=n){ if(L==l&&R==r)return tree[p]; int mid=l+r>>1; if(R<=mid)return query(L,R,p<<1,l,mid); if(L>mid)return query(L,R,p<<1|1,mid+1,r); return max(query(L,mid,p<<1,l,mid),query(mid+1,R,p<<1|1,mid+1,r)); }}T;void init__fa_son(){ for(int i=(1<<7)-1;i>=0;i--) for(int j=i;j>=0;j--) if((i&j)==j){ son[i].push_back(j); fa[j].push_back(i); }}void Up(int x,int y,int f){ for(int i=0;i<son[x].size();i++)cnt[0][(son[x][i]<<7)+y]+=f;//大区间降,小区间升 for(int i=0;i<fa[x].size();i++)cnt[1][(fa[x][i]<<7)+y]+=f;//大区间升,小区间降 cnt[2][(x<<7)+y]+=f;}void Get_ans0(int x,int y,int v){//大区间降,小区间升 for(int i=0;i<fa[y].size();i++)ans+=1ll*cnt[0][(x<<7)+fa[y][i]]*v;}void Get_ans1(int x,int y,int v){//大区间升,小区间降 for(int i=0;i<son[y].size();i++)ans+=1ll*cnt[1][(x<<7)+son[y][i]]*v;}void Get_ans2(int x,int y,int v){//重复 ans-=1ll*cnt[2][(x<<7)+y]*v;}void solve(int l,int r){ if(l>=r){ for(int i=l;i<=r;i++)Up(a[i]>>7,a[i]&((1<<7)-1),1); return; } int c=T.query(l,r).id,mid=l+r>>1; if(c>mid){//右区间小 solve(c+1,r);//小区间 for(int i=c+1;i<=r;i++)Up(a[i]>>7,a[i]&((1<<7)-1),-1);//删除小区间 solve(l,c-1);//不删除大区间 for(int i=c;i<=r;i++)Get_ans1(a[i]>>7,a[i]&((1<<7)-1),a[c]);//大区间升,小区间降 for(int i=c+1;i<=r;i++)Get_ans2(a[i]>>7,a[i]&((1<<7)-1),a[c]);//重复 Up(a[c]>>7,a[c]&((1<<7)-1),1); for(int i=c+1;i<=r;i++)Get_ans0(a[i]>>7,a[i]&((1<<7)-1),a[c]);//大区间降,小区间升 for(int i=c+1;i<=r;i++)Up(a[i]>>7,a[i]&((1<<7)-1),1); } else {//左区间小 solve(l,c-1);//小区间 for(int i=l;i<c;i++)Up(a[i]>>7,a[i]&((1<<7)-1),-1);//删除小区间 solve(c+1,r);//不删除大区间 for(int i=l;i<=c;i++)Get_ans1(a[i]>>7,a[i]&((1<<7)-1),a[c]);//大区间升,小区间降 for(int i=l;i<c;i++)Get_ans2(a[i]>>7,a[i]&((1<<7)-1),a[c]);//重复 Up(a[c]>>7,a[c]&((1<<7)-1),1); for(int i=l;i<c;i++)Get_ans0(a[i]>>7,a[i]&((1<<7)-1),a[c]);//大区间降,小区间升 for(int i=l;i<c;i++)Up(a[i]>>7,a[i]&((1<<7)-1),1); }}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); T.build();//建线段树 init__fa_son();//预处理父亲儿子 solve(1,n);//分治 cout<<ans<<'\n'; return 0;}
- 【CodeChef AUG16 T4】Chef and His Garden
- CodeChef Chef and Segments
- codechef Chef and sequence
- codechef Chef and Swaps
- Codechef Chef and Reversing
- Codechef Chef and Frogs
- Codechef Chef and Churu
- 【CodeChef】 Chef and Stones
- 【CodeChef】Chef and Interview
- codechef Chef and Churu
- 【codechef】Chef and His Friend (甲乙相遇的概率,分类)
- codechef Chef and easy problem
- codechef Chef and Left-Right
- codechef-Chef and Prime Divisors
- CodeChef Chef and Strange Operations
- Chef and Graph Queries (codechef)
- CodeChef Chef and Churu Problem
- codechef Chef and The Right Triangles 题解
- java 判断字符串是否为空,空字符串,或者空格
- 面试题08:Calculate BMI
- flask.jinja2模板中自动转义和取消转义的分析
- 技术贴子URL
- (数据结构)线性表之链表,java实现
- 【CodeChef AUG16 T4】Chef and His Garden
- 正则表达式
- 数论——快速幂
- java : apache cxf client 查询手机号码属地
- oracle基本操作
- windows PCHunter 系统信息查看 手工杀毒
- python os模块 常用命令
- 含头结点的C++尾插法创建简单链表并输出
- 单例模式详解