题目:https://ac.nowcoder.com/acm/contest/296/J

用点分治;

记录了值起伏的形态,二元组 (x,y) 表示有 x 个小于号,y 个大于号;

因为小于号和大于号都 >=2 就不合法了,所以状态是 3×3 的;

然后根据各种形态拼接...写了一晚上,最后连最简单的样例都过不了了...

感觉似乎走入歧途了,这样讨论太麻烦...

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
typedef long long ll;
int const xn=1e5+,inf=1e9;
int n,hd[xn],ct,to[xn<<],nxt[xn<<],w[xn],siz[xn],rt,mx,sum,wmx;
ll ans,b[][][xn];
bool vis[xn];
struct N{
int x,y,v;
N(int x=,int y=,int v=):x(x),y(y),v(v) {}
};
vector<N>tmp;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
void ins(int x,int y,int p){for(;p<=wmx;p+=(p&-p))b[x][y][p]++;}
int query(int x,int y,int p){int ret=; for(;p;p-=(p&-p))ret+=b[x][y][p]; return ret;}
int upquery(int x,int y,int p){return query(x,y,wmx)-query(x,y,p-);}
void getrt(int x,int fa)
{
siz[x]=; int nmx=;
for(int i=hd[x],u;i;i=nxt[i])
{
if((u=to[i])==fa)continue;
getrt(u,x); siz[x]+=siz[u];
if(siz[u]>nmx)nmx=siz[u];
}
nmx=max(nmx,sum-siz[x]);
if(nmx<mx)mx=nmx,rt=x;
}
void update(int t1,int t2,int a1)
{
if(t1==&&t2==)ans+=query(,,wmx)+query(,,wmx)+query(,,wmx)+query(,,wmx)+query(,,wmx)+upquery(,,a1)+query(,,a1),ans++;
//--\ , --/ , --__ , --`` , --``__ , --.\ , --/.
if(t1==&&t2==)ans+=query(,,a1)+query(,,wmx)+query(,,wmx)+query(,,wmx)+upquery(,,a1)+upquery(,,a1),ans++;
//--__/ , ``--\ , --__-- , ``--__ , ``--__`` , ``--\`
if(t1==&&t2==)ans+=query(,,wmx)+query(,,wmx)+upquery(,,a1)+upquery(,,a1)+upquery(,,a1),ans++;//``\--\ , ``\--__ , --\__`` , ``\--__`` , ``\.`
if(t1==&&t2==)ans+=query(,,a1)+query(,,wmx)+upquery(,,a1)+query(,,wmx)+query(,,a1)+query(,,a1),ans++;
//__``-- , __--/ , __-- \ , __--`` , __--``__ , __--``.
if(t1==&&t2==)ans+=query(,,a1)+query(,,a1)+upquery(,,a1)+upquery(,,a1),ans++;//--``__-- , --``__/ , --__``-- , --__``\ if(t1==&&t2==)ans+=upquery(,,a1)+upquery(,,a1),ans++;//.\--__ , .\--\
if(t1==&&t2==)ans+=query(,,wmx)+query(,,a1)+query(,,wmx)+query(,,a1)+query(,,a1),ans++;// // , /``__ , /--`` , /--``__ , /`.
if(t1==&&t2==)ans+=query(,,a1)+query(,,a1),ans++;// /.--`` , /./
}
void dfs(int x,int fa,int s1,int s2)//to rt
{
if(w[x]<w[fa])s1++; if(w[x]>w[fa])s2++;
if((s1>=&&s2==&&w[rt]>w[x])||(s1==&&s2>=&&w[rt]<w[x]))return;//&&
int t1=min(s1,),t2=min(s2,);
ans+=query(,,wmx); update(t1,t2,w[x]);
//printf("x=%d ans=%lld t1=%d t2=%d\n",x,ans,t1,t2);
tmp.pb(N(t2,t1,w[x]));
for(int i=hd[x],u;i;i=nxt[i])
if((u=to[i])!=fa&&!vis[u])dfs(u,x,s1,s2);
}
/*
void update2(int t1,int t2,int a1)
{
if(t1==0&&t2==0)ans+=query(0,1,wmx)+query(0,2,wmx)+query(1,0,wmx)+query(1,1,wmx)+query(2,0,mx),ans++;//--__ , --\__ , --`` , --``__ , --/
if(t1==0&&t2==1)ans+=query(0,2,wmx)+query(1,0,wmx)+query(2,0,a1)+query(0,1,wmx),ans++;//``\--__ , __--__ , /``__ , ``--__
if(t1==0&&t2==2)ans+=query(0,1,wmx)+query(0,2,wmx)+query(1,0,a1),ans++;//``--\ , ``\--\ , __``\
if(t1==1&&t2==0)ans+=query(0,1,wmx)+query(0,2,a1)+query(1,0,wmx)+upquery(1,1,a1)+query(2,0,wmx),ans++;//--__-- , --\__`` , __--`` , --``__-- , /--``
if(t1==1&&t2==1)ans+=upquery(1,0,a1)+upquery(2,0,a1),ans++;//__--``__ , /--``__
if(t1==2&&t2==0)ans+=query(0,1,a1)+query(1,0,wmx)+upquery(1,1,a1)+query(2,0,wmx),ans++;//--__/ , __--/ , --``__/ , //
}
void dfs2(int x,int fa,int s1,int s2)//from rt
{
if(w[x]<w[fa])s2++; if(w[x]>w[fa])s1++;
if((s1>=2&&s2==1)||(s1==1&&s2>=2))return;
int t1=min(s1,2),t2=min(s2,2);
ans+=query(0,0,wmx); update2(t1,t2,w[x]);
tmp.pb(N(t1,t2,w[x]));
for(int i=hd[x],u;i;i=nxt[i])
if((u=to[i])!=fa&&!vis[u])dfs2(u,x,s1,s2);
}
*/
void work(int x,int ss)
{
printf("x=%d\n",x);
vis[x]=;//
memset(b,,sizeof b);
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]])continue;
dfs(u,x,,);
printf("u=%d\n",u);
for(int j=;j<tmp.size();j++){ins(tmp[j].x,tmp[j].y,tmp[j].v);
printf("t(%d,%d,%d)\n",tmp[j].x,tmp[j].y,tmp[j].v);}
printf("ans=%lld\n",ans);
tmp.clear();
}
/* //无序
memset(b,0,sizeof b);
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]])continue;
dfs2(u,x,0,0);
for(int j=0;j<tmp.size();j++)ins(tmp[j].x,tmp[j].y,tmp[j].v);
tmp.clear();
}
*/
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]])continue;
sum=(siz[u]>siz[x]?ss-siz[x]:siz[x]); mx=inf;
getrt(u,); work(u,sum);//(u,0)
}
}
int main()
{
int T=rd();
while(T--)
{
n=rd();
ct=; memset(hd,,sizeof hd); wmx=;
memset(vis,,sizeof vis);
for(int i=;i<=n;i++)w[i]=rd(),wmx=max(wmx,w[i]);
for(int i=,x,y;i<n;i++)x=rd(),y=rd(),add(x,y),add(y,x);
sum=n; mx=inf; getrt(,);//
ans=; work(rt,sum);
printf("%lld\n",ans+n);//
}
return ;
}

艰难尝试

然后看了看AC代码,也有一篇拼形态的,看了半天没看懂...

其实应该是不用拼形态的,直接考虑拼起来以后的大于号、小于号情况来判断是否对两个端点的值有要求;

如果拼起来以后是 (0,~) 或 (~,0) 或 (1,1),那么对前后端点值的大小是没有限制的;

如果是 (1,~),小于号只有一个,那么一定是两个下降的段,要求前端的值 <= 后端的值,才可以从小于号的地方断开,成为有序的;

如果是 (~,1),大于号只有一个,同理,前端的值 >= 后端的值;

所以只要考虑拼完以后的形态就可以了,讨论变得简单许多;

注意判掉不合法的情况,而且每个点自己单独也是一种合法的情况;

清空树状数组时不要暴力使复杂度剧增,可以再 dfs 一遍,把刚才加上的减去;

可以对值域先离散化,加快树状数组的查询;

注意点分治不要写错;

注意本题没有对 1e9+7 取模呵呵。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
typedef long long ll;
int const xn=1e5+,inf=1e9;
int n,hd[xn],ct,to[xn<<],nxt[xn<<],w[xn],siz[xn],mx,sum,rt,wmx,b[][][xn];
ll ans;
bool vis[xn];
struct N{
int u,v,w;
N(int u=,int v=,int w=):u(u),v(v),w(w) {}
};
vector<N>tmp;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
void ins(int x,int y,int p,int v){for(;p<=wmx;p+=(p&-p))b[x][y][p]+=v;}
int query(int x,int y,int p){if(!p)return ; int ret=; for(;p;p-=(p&-p))ret+=b[x][y][p]; return ret;}
int upquery(int x,int y,int p){return query(x,y,wmx)-query(x,y,p-);}
void getrt(int x,int fa)
{
siz[x]=; int nmx=;
for(int i=hd[x],u;i;i=nxt[i])
{
if((u=to[i])==fa||vis[u])continue;
getrt(u,x); siz[x]+=siz[u];
if(nmx<siz[u])nmx=siz[u];
}
nmx=max(nmx,sum-siz[x]);
if(nmx<mx)mx=nmx,rt=x;
}
void update(int s1,int s2,int w)
{
ans++;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
{
int t1=s1+i,t2=s2+j;
if(t1>=&&t2>=)continue;
if(!t1||!t2||(t1==&&t2==))ans+=query(i,j,wmx);
else if(t1==)ans+=upquery(i,j,w);
else if(t2==)ans+=query(i,j,w);
}
}
void dfs(int x,int fa,int s1,int s2)
{
if(w[x]<w[fa])s1++; if(w[x]>w[fa])s2++;
if(s1>)s1=; if(s2>)s2=;
if((s1==&&s2==)||(s1==&&s2==&&w[x]>w[rt])||(s1==&&s2==&&w[x]<w[rt]))return;
update(s1,s2,w[x]); tmp.pb(N(s1,s2,w[x]));
//printf("x=%d s1=%d s2=%d ans=%d\n",x,s1,s2,ans);
for(int i=hd[x],u;i;i=nxt[i])
if((u=to[i])!=fa&&!vis[u])dfs(u,x,s1,s2);
}
void clear(int x,int fa,int s1,int s2)
{
if(w[x]<w[fa])s1++; if(w[x]>w[fa])s2++;
if(s1>)s1=; if(s2>)s2=;
if((s1==&&s2==)||(s1==&&s2==&&w[x]>w[rt])||(s1==&&s2==&&w[x]<w[rt]))return;
ins(s2,s1,w[x],-);
for(int i=hd[x],u;i;i=nxt[i])
if((u=to[i])!=fa&&!vis[u])clear(u,x,s1,s2);
}
void work(int x,int ss)
{
//printf("x=%d\n",x);
vis[x]=;
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]])continue;
dfs(u,x,,); int siz=tmp.size();
for(int j=;j<siz;j++)ins(tmp[j].v,tmp[j].u,tmp[j].w,);
tmp.clear();
}
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]])continue;
clear(u,x,,);
}
for(int i=hd[x],u;i;i=nxt[i])
{
if(vis[u=to[i]])continue;
sum=(siz[u]>siz[x]?ss-siz[x]:siz[u]);//siz[u]!
mx=inf; getrt(u,); work(rt,sum);
}
}
int tt[xn];
int main()
{
int T=rd();
while(T--)
{
n=rd();
ct=; for(int i=;i<=n;i++)hd[i]=;
for(int i=;i<=n;i++)w[i]=rd(),tt[i]=w[i];
sort(tt+,tt+n+); wmx=unique(tt+,tt+n+)-tt-;
for(int i=;i<=n;i++)w[i]=lower_bound(tt+,tt+wmx+,w[i])-tt;
for(int i=,x,y;i<n;i++)x=rd(),y=rd(),add(x,y),add(y,x);
ans=; for(int i=;i<=n;i++)vis[i]=;
mx=inf; sum=n; getrt(,); work(rt,n);
printf("%lld\n",ans+n);
}
return ;
}

牛客网字节跳动冬令营网络赛J Sortable Path on Tree —— 点分治的更多相关文章

  1. 字节跳动冬令营网络赛 D.The Easiest One(贪心 数位DP)

    题目链接 \(x:\ 11010011\) \(y:\ 10011110\) (下标是从高位往低位,依次是\(1,2,...,n\)) 比如对于这两个数,先找到最高的满足\(x\)是\(0\),\(y ...

  2. 字节跳动冬令营网络赛 Solution

    A:Aloha Unsolved. B:Origami Unsolved. 题意: 初始的时候有一张纸,可以从左边往右边折叠,或者从右边往左边折叠 每次折叠的长度不能超过现有宽度,最后折叠到长度为1 ...

  3. 计蒜客 2019南昌邀请网络赛J Distance on the tree(主席树)题解

    题意:给出一棵树,给出每条边的权值,现在给出m个询问,要你每次输出u~v的最短路径中,边权 <= k 的边有几条 思路:当时网络赛的时候没学过主席树,现在补上.先树上建主席树,然后把边权交给子节 ...

  4. 牛客网多校第4场 J Hash Function 【思维+并查集建边】

    题目链接:戳这里 学习博客:戳这里 题意: 有n个空位,给一个数x,如果x%n位数空的,就把x放上去,如果不是空的,就看(x+1)%n是不是空的. 现在给一个已经放过数的状态,求放数字的顺序.(要求字 ...

  5. 牛客网多校训练第一场 J - Different Integers(树状数组 + 问题转换)

    链接: https://www.nowcoder.com/acm/contest/139/J 题意: 给出n个整数的序列a(1≤ai≤n)和q个询问(1≤n,q≤1e5),每个询问包含两个整数L和R( ...

  6. 牛客网多校第7场 J Sudoku Subrectangles 【构造】

    题目:戳这里 题意:给一个n*m的矩阵,里面由a~z及A~Z构成,问有多少个子矩阵满足任意一行或一列中都没有相同的字母. 解题思路:左上角和右下角两点可以确定一个矩阵.可以先预处理出来每个点作为一个矩 ...

  7. 南昌网络赛J. Distance on the tree 树链剖分+主席树

    Distance on the tree 题目链接 https://nanti.jisuanke.com/t/38229 Describe DSM(Data Structure Master) onc ...

  8. 2019南昌邀请赛网络赛:J distance on the tree

    1000ms 262144K   DSM(Data Structure Master) once learned about tree when he was preparing for NOIP(N ...

  9. 南昌网络赛J. Distance on the tree 树链剖分

    Distance on the tree 题目链接 https://nanti.jisuanke.com/t/38229 Describe DSM(Data Structure Master) onc ...

随机推荐

  1. OpenCV玩耍(一)批量resize一个文件夹里的所有图像

    鉴于用caffe做实验的时候,里面牵扯到一个问题是必须将训练集和测试集都转成256*256的图像,而官网给出的代码又不会用,所以我用opencv转了.其实opencv只转一幅图会很简单,关键在于“批量 ...

  2. 鼠标画矩形openCV

    #include <cv.h> #include <highgui.h> #include <stdio.h> /*鼠标画矩形*/ void my_mouse_ca ...

  3. Java语言实现简单FTP软件------>辅助功能模块FTP站点管理的实现(十二)

    1.FTP站点管理 点击"FTP站点管理"按钮,弹出对话框"FTP站点管理",如下图 1) 连接站点 在FTP站点管理面板上选好要连接的站点,点击"连 ...

  4. python+NLTK 自然语言学习处理八:分类文本一

    从这一章开始将进入到关键部分:模式识别.这一章主要解决下面几个问题 1 怎样才能识别出语言数据中明显用于分类的特性 2 怎样才能构建用于自动执行语言处理任务的语言模型 3 从这些模型中我们可以学到那些 ...

  5. Gateway

    网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连.网关的结构也和路由器类似,不同的是互连层.网关既可以用于广域网互连,也可以用于局域网互连. 网关是一种充当转换重 ...

  6. .vimrc .bashrc

    怕丢了,赶快保存! .bashrc # switch caps lock with escxmodmap -e 'clear Lock' -e 'keycode 0x42 = Escape'sudo ...

  7. 每天一个Linux命令(33)cal命令

          cal命令用于显示当前日历,或者指定日期的日历.   (1)用法: 用法: cal [选项]  [[[日] 月] 年] (2)功能:       功能:  用于查看日历等时间信息,如只有一 ...

  8. php 实现简单抽奖

    首先有一组数据,里面有中奖的物品和概率 $base_data = [ ['name'=>'特等奖','num'=>1], ['name'=>'一等奖','num'=>5], [ ...

  9. 使用mongify将sqlserver数据导入到mongodb

    最近需要将sqlserver数据导入到mongodb中,在github上搜了一圈,发现两个项目有点适合 mongify sql2mongodb 先试了下sql2mongodb(有个好名字果然有好处啊) ...

  10. ML三(人工神经网络)

    人工神经网络 Artificial Neural Nerworks 基本术语概念: 人工神经网络(Artificial Neural Networks,ANN) 感知器(Perceptron):以一个 ...