来自FallDream的博客。未经允许,请勿转载,谢谢。

----------------------------------------------------

A.积分,不会  以后补

B.给定一个n*m的矩阵,每个点是0或者1,然后q个操作,每次把一个位置取反,然后询问最大的全是1的正方形的边长。n*m<=4000000 , q<=3900

题解:我们用一个线段树把所有行维护起来,然后每一行对每一列维护这个行区间的这一列的u和d,u表示从最下面一个最多有多少个连续的1,d表示从上面网下面最多有多少个连续的1,这两个参数是很好合并的。然后我们考虑计算过中线的答案。我们用两个指针ij,再用两个单调队列,维护u和d单调下降。每当 i - j + 1> u[tail] + d[tail] 的时候,我们把j指针往前移。最后我们用i - j + 1更新答案。

复杂度qmlogn  如果n<m我们把nm交换一下。

最近被奇怪的代码风格洗脑了,写了一个不像是我写的程序(听我解释,我真的不是抄的.....) 其实我真正的代码风格像C题那样就是一团垃圾

#include<iostream>
#include<cstdio>
#define MN 2000
#define TEST
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
} inline int cread()
{
char ch = getchar();
while(ch != '.' && ch != 'X') ch = getchar();
return ch == '.' ? : ;
} int n , m , q , qx[MN + ] , ltop , qy[MN + ] , rtop , ltail , rtail;
bool *s[MN + ] , rev; struct Segment_Tree{
int ans , w;
int *u , *d;
Segment_Tree *l , *r;
void init(int x)
{
ans = ;
for(int i = ; i <= n ; ++i)
u[i] = d[i] = s[i][x] , ans |= s[i][x];
} void update()
{
ans = max ( l->ans , r->ans ); int x , k = ;
for(int i = ; i <= n ; ++i)
{
u[i] = l -> d[i];
d[i] = r -> u[i];
} qx[ltop = ] = qy[rtop = ] = ;
ltail = rtail = ; for ( int i = ; i <= n ; ++i)
{
while(u[i] <= u[qx[ltop]] && ltop >= ltail) ltop --;
while(d[i] <= d[qy[rtop]] && rtop >= rtail) rtop --; qx[++ ltop] = i;
qy[++ rtop] = i; while(i - k + > u[qx[ltail]] + d[qy[rtail]] && i > k)
{
++ k;
if(qx[ltail] < k) ltail ++;
if(qy[rtail] < k) rtail ++;
}
ans = max(ans , i - k + );
} for(int i = ; i <= n ; ++i)
{
u[i] = ( l -> u[i] == l -> w) ? r -> u[i] + l -> w : l -> u[i];
d[i] = ( r -> d[i] == r -> w) ? l -> d[i] + r -> w : r -> d[i];
}
} void modify(int x , int lt = , int rt = m)
{
if(lt == rt) { init(x); return;}
int mid = lt + rt >> ;
if(x <= mid) l -> modify(x , lt , mid);
else r -> modify(x , mid + , rt);
update();
} Segment_Tree(int lt , int rt )
{
u = new int [n + ];
d = new int [n + ];
w = rt - lt + ;
if(lt == rt) { init(lt); return;}
int mid = lt + rt >> ;
l = new Segment_Tree(lt , mid);
r = new Segment_Tree(mid + , rt);
update();
} }*rt; int main()
{
#ifdef TEST
freopen("s.in" , "r" , stdin);
freopen("s.out" , "w" , stdout);
#endif n = read(); m = read(); q = read();
if( n > m) swap(n , m),rev = true;
for(int i = ; i <= n ; ++i)
s[i] = new bool [m + ]; if(!rev)
for(int i = ; i <= n ; ++i)
for(int j = ; j <= m ; ++j)
s[i][j] = cread();
else
for(int i = ; i <= m ; ++i)
for(int j = ; j<= n ; ++j)
s[j][i] = cread(); rt = new Segment_Tree( , m); for(int i = ; i <= q ; ++i)
{
int x = read() , y = read();
if(rev) swap(x , y);
s[x][y] ^= ;
rt -> modify(y);
printf("%d\n" , rt -> ans);
}
return ;
}

C.给定一棵n个点树,每个点可以涂成白的或者黑的。给定b条链和b个权值bi,表示这条链上的点全是黑色时候能得到bi的贡献。还有a条链和a个权值,表示全部涂成白色能得到的贡献。你要求出最大贡献。n<=100000  a,b<=30000  3s

题解:神题

最小割,很显然黑白链就是一个二分图。但是直接建图是不行的,所以我们考虑优化一下,把树拿去树剖一下,然后建两棵线段树,一棵只能往下走,一棵只能往上走。每条链对两棵线段树上的对应的log个区间建边,最后跑一次最小割。复杂度很玄学,就算O(能过)吧。

ditoly真的强,居然在现场想出了这个做法...%%%

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 800000
#define MAXL 10000000
#define MV 860000
#define MAXN 100000
#define MN 100000
#define S 0
#define tt 860001
#define INF 2000000000
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-; ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-''; ch=getchar();}
return x*f;
}
int dn=,cnt=,ans=,n,B,W,head2[MAXN+],head[MV+],top[MAXN+],qx[MV+],qtop,tail;
int dfn[MAXN+],mx[MAXN+],size[MAXN+],dep[MAXN+],fa[MAXN+],q[MV+],tp[MV+];
struct edge{
int to,next,w;
}e[MAXL*+];
struct edge2{
int to,next;
}e2[MAXN*+];
struct TREE{
int l,r;
}T[MN*+]; inline void ins(int f,int t){e2[++cnt].next=head2[f];head2[f]=cnt;e2[cnt].to=t;}
inline void ins(int f,int t,int w){e[++cnt].next=head[f];head[f]=cnt;e[cnt].to=t;e[cnt].w=w;}
inline void insw(int f,int t,int w){ins(f,t,w);ins(t,f,);} void dfs(int x,int f)
{
size[x]=;mx[x]=;fa[x]=f;int maxn=;
for(int i=head2[x];i;i=e2[i].next)if(e2[i].to!=f)
{
dep[e2[i].to]=dep[x]+;dfs(e2[i].to,x);
size[x]+=size[e2[i].to];
if(size[e2[i].to]>maxn){maxn=size[e2[i].to];mx[x]=e2[i].to;}
}
} void dfs2(int x,int t)
{
top[x]=t;dfn[x]=++dn;
if(mx[x])dfs2(mx[x],t);
for(int i=head2[x];i;i=e2[i].next)if(!dfn[e2[i].to])
{dfs2(e2[i].to,e2[i].to);}
} void build(int x,int l,int r)
{
T[x].l=l;T[x].r=r;if(l==r)return;
int mid=(l+r)>>;
insw(x,x<<,INF);insw(x,x<<|,INF);
insw((x<<)+*MN,x+*MN,INF);insw((x<<|)+*MN,x+*MN,INF);
build(x<<,l,mid);build(x<<|,mid+,r);
} void insert(int from,int x,int l,int r)
{
// cout<<"insert"<<from<<" "<<x<<" "<<l<<" "<<r<<" "<<lt<<" "<<rt<<endl;
if(T[x].l==l&&T[x].r==r){insw(from,x,INF);insw(from,x+MN*,INF);return;}
int mid=(T[x].l+T[x].r)>>;
if(r<=mid)insert(from,x<<,l,r);
else if(l>mid)insert(from,x<<|,l,r);
else {insert(from,x<<,l,mid);insert(from,x<<|,mid+,r);}
} void insert2(int to,int x,int l,int r)
{
// cout<<"insert2"<<to<<" "<<x<<" "<<l<<" "<<r<<" "<<lt<<" "<<rt<<endl;
if(T[x].l==l&&T[x].r==r){insw(x,to,INF);insw(x+MN*,to,INF);return;}
int mid=(T[x].l+T[x].r)>>;
if(r<=mid)insert2(to,x<<,l,r);
else if(l>mid)insert2(to,x<<|,l,r);
else {insert2(to,x<<,l,mid);insert2(to,x<<|,mid+,r);}
} bool bfs()
{
memset(q,,sizeof(q));int i,j;
for(q[qx[qtop=i=]=S]=;i<=qtop;i++)
for(int j=tp[qx[i]]=head[qx[i]];j;j=e[j].next)if(!q[e[j].to]&&e[j].w)
q[qx[++qtop]=e[j].to]=q[qx[i]]+;
return q[tt]>;
} int solve(int x,int f)
{
// cout<<"solve"<<x<<" "<<f<<endl;
if(x==tt)return f;int used=;
for(int&i=tp[x];i;i=e[i].next)
if(e[i].w&&q[e[i].to]==q[x]+)
{
int w=solve(e[i].to,min(f-used,e[i].w));
used+=w;e[i].w-=w;e[i^].w+=w;
if(e[i].w) tp[x]=i;
if(used==f)return f;
}
if(!used)q[x]=-;
return used;
} int main()
{
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
n=read();B=read();W=read();
for(int i=;i<n;i++)
{int u=read(),v=read();ins(u,v),ins(v,u);}
cnt=;dfs(,);dfs2(,);
build(,,n);
for(int i=;i<=B;++i)
{
int u=read(),v=read(),x=read();insw(S,N+i,x);ans+=x;
while(top[u]!=top[v])
{
// cout<<u<<" "<<v<<" "<<top[u]<<" "<<top[v]<<endl;
if(dep[top[u]]>dep[top[v]])
{insert(N+i,,dfn[top[u]],dfn[u]);u=fa[top[u]];}
else
{insert(N+i,,dfn[top[v]],dfn[v]);v=fa[top[v]];}
}
if(dfn[u]>dfn[v])swap(u,v);insert(N+i,,dfn[u],dfn[v]);
}
for(int i=;i<=W;++i)
{
int u=read(),v=read(),x=read();insw(N+i+B,tt,x);ans+=x;
while(top[u]!=top[v])
{
// cout<<u<<" "<<v<<" "<<top[u]<<" "<<top[v]<<endl;
if(dep[top[u]]>dep[top[v]])
{insert2(N+i+B,,dfn[top[u]],dfn[u]);u=fa[top[u]];}
else
{insert2(N+i+B,,dfn[top[v]],dfn[v]);v=fa[top[v]];}
}
if(dfn[u]>dfn[v])swap(u,v);insert2(N+i+B,,dfn[u],dfn[v]);
}
while(bfs())ans-=solve(S,INF);
printf("%d\n",ans);
return ;
}

[3.19FJ四校联考]的更多相关文章

  1. [2017/5/28]FJ四校联考

    来自FallDream的博客,未经允许,请勿转载,谢谢. 话说这一段时间算是过去了,好久好久之后终于又有联考了  没想到这次到我们学校出题,昨天才想起来,临时花一天赶了一套,我出了一个sbFFT,质量 ...

  2. [四校联考P3] 区间颜色众数 (主席树)

    主席树 Description 给定一个长度为 N 颜色序列A,有M个询问:每次询问一个区间里是否有一种颜色的数量超过了区间的一半,并指出是哪种颜色. Input 输入文件第一行有两个整数:N和C 输 ...

  3. 四校联考 tree3

    我们考虑计算红色点与非红色点的对数. 我们用f[i][j]表示i的子树中有j个红色点的概率,将i所有子树合并. 接着我们对于每一个状态,枚举i是红色还是非红色算概率. 同时我们可以求出i和i子树内一个 ...

  4. 【四校联考】【比赛题解】FJ NOIP 四校联考 2017 Round 7

    此次比赛为厦门一中出题.都是聚劳,不敢恭维. 莫名爆了个0,究其原因,竟然是快读炸了……很狗,很难受. 话不多说,来看看题: [T1] 题意: 样例: PS:1<=h[i]<=100000 ...

  5. szoj461【四校联考0430】挑战

    传送门:(涉及版权忽略) [题解] 我们发现n的范围很小,提示我们可以折半,然后我们就会了O(T2^(n/2)*n)的做法,然而会T. 考虑如何优化.直接排序会多一个log(2^(n/2))也就是n, ...

  6. 三校联考 Day3

    三校联考 Day3 大水题 题目描述:给出一个圆及圆上的若干个点,问两个点间的最远距离. solution 按极角排序,按顺序枚举,显然距离最远的点是单调的,线性时间可解出答案. 大包子的束缚 题目描 ...

  7. 【赛时总结】NOIP2018-三校联考1024

    ◇NOIP三校联考-1024◇ 发现以前的博客写得似乎都很水……基本上都没什么阅读量QwQ 决定改过自新╰( ̄ω ̄o) 就从这篇博客开始吧~ 现场考得无地自容,看到题解才发现一些东西……(我第三题还没 ...

  8. [2019多校联考(Round 6 T3)]脱单计划 (费用流)

    [2019多校联考(Round 6 T3)]脱单计划 (费用流) 题面 你是一家相亲机构的策划总监,在一次相亲活动中,有 n 个小区的若干男士和 n个小区的若干女士报名了这次活动,你需要将这些参与者两 ...

  9. [多校联考2019(Round 5 T1)] [ATCoder3912]Xor Tree(状压dp)

    [多校联考2019(Round 5)] [ATCoder3912]Xor Tree(状压dp) 题面 给出一棵n个点的树,每条边有边权v,每次操作选中两个点,将这两个点之间的路径上的边权全部异或某个值 ...

随机推荐

  1. JAVA接口基础知识总结

    1:是用关键字interface定义的. 2:接口中包含的成员,最常见的有全局常量.抽象方法. 注意:接口中的成员都有固定的修饰符. 成员变量:public static final     成员方法 ...

  2. Beta冲刺Day3

    项目进展 李明皇 今天解决的进度 完善了程序的运行逻辑(消息提示框等) 明天安排 前后端联动调试 林翔 今天解决的进度 向微信官方申请登录验证session以维护登录态 明天安排 继续完成维护登录态 ...

  3. 部分和问题 nyoj

    部分和问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K.   输入 首先, ...

  4. 用phpcms切换中英文网页的方法(不用解析二级域名)、phpcms完成pc和手机端切换(同一域名)

    AA.phpcms进行双语切换方法(不用解析二级域名)作者:悦悦 博客地址:http://www.cnblogs.com/nuanai/ phpcms进行两种语言的切换,有一把部分的人都是进行的二级域 ...

  5. Java排序算法之快速排序

    Java排序算法之快速排序 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分 ...

  6. babel基本用法

    babel-cli babel-cli是本地使用编译js文件 1.安装: cnpm i babel-cli babel-preset-env -D 2.配置packjson: "script ...

  7. 详解k8s一个完整的监控方案(Heapster+Grafana+InfluxDB) - kubernetes

    1.浅析整个监控流程 heapster以k8s内置的cAdvisor作为数据源收集集群信息,并汇总出有价值的性能数据(Metrics):cpu.内存.网络流量等,然后将这些数据输出到外部存储,如Inf ...

  8. 剑指offer-链表中环的入口节点

    题目描述 一个链表中包含环,请找出该链表的环的入口结点. 解题思路 解决这个问题的第一步是如何确定一个链表中包含环.可以定义两个指针,同时从链表的头结点出发,一个指针一次走一步,另一个一次走两步.如果 ...

  9. 增加Linux虚拟机的硬盘空间

    原配置为40G,现需要增加到60G,操作方法如下: 一.虚拟机关机,在编辑设置里调整硬盘空间到60G 二.虚拟机开机,扩展硬盘空间 1.安装gparted,命令如下 sudo apt-get inst ...

  10. 租户、租户管理员、部门管理员和开发者在APIGW中的角色

    一.参与者 1.vdcId:租户 2.运营管理员 operator: 一种角色 创建开发商 审批外置服务,如:hadoop集群 审批内置服务,如:<API使用申请> 3.租户管理员     ...