10.1综合强化刷题 Day3
括号序列(bracket)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK有一个括号序列,但这个序列不一定合法。
一个合法的括号序列如下:
()是合法的括号序列。
若A是合法的括号序列,则(A)是合法的括号序列。
若A和B分别是合法的括号序列,则AB是合法的括号序列。
LYK想通过尽可能少的操作将这个不一定合法的括号序列变成合法的括号序列。一次修改操作是将某个字符变成另一个字符。
你能帮帮它吗?
输入格式(bracket.in)
一行一个字符串S。
输出格式(bracket.out)
一个数表示最少修改次数。
输入样例
()))
输出样例
1
样例解释
将第二个字符修改成(即可。
数据范围
对于30%的数据|S|<=10。
对于60%的数据|S|<=1000。
对于100%的数据|S|<=100000。且|S|是偶数。
一个比较水的题,似乎就是一个比较裸地括号匹配。我们可以用一个比较简单的栈模拟(我用的是队列模拟)就可以A掉的、、
我们每次读入一个字符,然后判断如果这个字符是(那么我们让他进队,即tail++,然后如果读入的字符是一个)那么我们判断在这个字符的前面时候存在(,如果存在,我们就讲这个()全部消掉,即队中的一定只是(,那我们消掉的时候只要让他tail--就好了,当然我们要保证head<=tail。如果对中没有(可以将)消掉,那么说明这个)一定是不合法的我们一定要将这个)进行修改,改成(然后将其入队,tail++。
我们一直这样处理,最后一定会出现这样的情况((((((,如果有)的会就被消掉了啊。。。那么我们只需要将后面的(修改成)就好了,也就是说我们最后进行修改的个数极为(的个数除以2,(的个数即为队中元素的个数,队中的元素的个数为head。
这样这道题就已经AC了
来,看看代码、、、
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100010
using namespace std;
char s[N];
int head,tail,ans;
int read()
{
,f=; char ch=getchar();
') ch=getchar();
+ch-',ch=getchar();
return x*f;
}
int main()
{
freopen("bracket.in","r",stdin);
freopen("bracket.out","w",stdout);
cin>>s;
head=tail=;
int l=strlen(s);
;i<l;i++)
{
if(s[i]=='(') tail++;
else
{
if(tail>head) tail--;
else tail++,ans++;
}
}
;
printf("%d",ans);
;
}
AC代码
公交车(bus)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK在玩一个游戏。
有k群小怪兽想乘坐公交车。第i群小怪兽想从xi出发乘坐公交车到yi。但公交车的容量只有M,而且这辆公交车只会从1号点行驶到n号点。
LYK想让小怪兽们尽可能的到达自己想去的地方。它想知道最多能满足多少小怪兽的要求。
当然一群小怪兽没必要一起上下车,它们是可以被分开来的。
输入格式(bus.in)
第一行三个数k,n,M。
接下来k行每行3个数xi,yi和ci。其中ci表示第i群小怪兽的小怪兽数量。
输出格式(bus.out)
一个数表示最多有多少只小怪兽能满足要求。
输入样例
3 5 3
1 3 4
3 5 2
1 5 3
输出样例
5
样例解释
第一群的3只小怪兽在1号点上车,并在3号点下车。
第二群的2只小怪兽在3号点上车,5号点下车。
数据范围
对于30%的数据小怪兽的总数不超过10只,n<=10。
对于另外30%的数据k,n<=1000。
对于100%的数据1<=n<=20000,1<=k<=50000,1<=M<=100,1<=ci<=100,1<=xi<yi<=n。
不会正解打了个搜索,碰到了30分、、
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 20010
using namespace std;
int n,m,k,ans,sum[N];
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
struct node
{
int to,val;
node() {}
node(int to,int val):to(to),val(val) {}
};
vector<node>G[N];
void DFS(int num,int s,int people)
{
)
{
ans=max(ans,s);
return;
}
people+=sum[num];
sum[num]=;
;i<G[num].size();++i)
{
int v=G[num][i].to;
int ps=G[num][i].val;
if(ps<=k-people)
{
sum[v]+=-ps;
DFS(num+,s+ps,people+ps);
}
else if((people<k)&&(ps+people>k))
{
sum[v]+=people-k;
DFS(num+,s+k-people,k);
}
}
DFS(num+,s,people);
return;
}
int main()
{
freopen("bus.in","r",stdin);
freopen("bus.out","w",stdout);
m=read(),n=read(),k=read();
int x,y,z;
;i<=m;++i)
{
x=read(),y=read(),z=read();
G[x].push_back(node(y,z));
}
DFS(,,);
printf("%d\n",ans);
;
}
dfs
看到这个题后我们脑子里一定会闪过这样一个经典题目,有n个区间,找尽可能多的区间使得区间之间互不相交。(啊,这不就是线段覆盖那道题吗?!)
对于这道经典的题目我们使用的贪心的做法,将所有的线段按右端点进行排序枚举每一个区间,然后按照能取就取的原则进行贪心。
但是这个题和那个经典题目是有很大的区别的,我们在这个经典问题中的线段是不能相交的,并且我们知道车有一个容量,我们每次都可以上c(容量)的人。
我们对于每一个区间,求这一群怪兽能过几只 维护一个f数组 f[i]表示i这个时刻 车上已经坐了几只怪兽了
[X,Y] Z
for (int i=X; i<Y; i++)
MAX=max(MAX,f[i]);
t=min(Z,M-MAX);
for (int i=X; i<Y; i++) f[i]+=t;
ans+=t
cout<<ans;
1.区间加 2.区间查询最大值,看到这两个操作,我们就可以很容易的想到线段树了 这样的时间复杂度为 klgn
这样这个事情就干完了、、
具体的来说就是我们先按右端点进行排序,然后对于每一个怪兽在车上呆的区间进行一个区间查询,然后在能上就上进行一下区间修改,最后统计个数,这样就搞定了
来,上代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
int n,m,c,a,b,x,q,p,ans,minn;
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
struct Tree
{
int l,r,w,f;
}tree[N];
struct Node
{
int x,y,z;
}node[N];
int cmp(Node a,Node b)
{
return a.y<b.y;
}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
if(tree[k].l==tree[k].r)
{
tree[k].w=c;
return ;
}
;
build(k<<,l,mid);
build(k<<|,mid+,r);
tree[k].w=tree[k<<].w+tree[k<<|].w;
}
void down(int k)
{
tree[k<<].f+=tree[k].f;
tree[k<<|].f+=tree[k].f;
tree[k<<].w+=(tree[k<<].r-tree[k<<].l+)*tree[k].f;
tree[k<<|].w+=(tree[k<<|].r-tree[k<<|].l+)*tree[k].f;
tree[k].f=;
}
void change(int k)
{
if(tree[k].l>=a&&tree[k].r<=b)
{
tree[k].w+=(tree[k].r-tree[k].l+)*x;
tree[k].f+=x;
return ;
}
if(tree[k].f) down(k);
;
);
|);
tree[k].w=tree[k<<].w+tree[k<<|].w;
}
void ask(int k)
{
if(tree[k].r<a||tree[k].l>b) return ;
if(tree[k].l==tree[k].r)
{
minn=min(minn,tree[k].w);
return ;
}
if(tree[k].f) down(k);
;
);
|);
}
int main()
{
m=read(),n=read(),c=read();
build(,,n);
;i<=m;i++)
{
node[i].x=read(),node[i].y=read();
node[i].z=read();node[i].y--;
}
sort(node+,node++m,cmp);
;i<=m;i++)
{
a=node[i].x,b=node[i].y;
minn=);
),ans+=node[i].z;
),ans+=minn;
}
printf("%d",ans);
}
诡异的60分的线段树做法
区间求最小值的时候进行修改的时候只修改一个点的值,因为我们线段树维护的是最小值,而非和
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
int n,m,c,a,b,x;
long long ans,minn;
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
struct Tree
{
int l,r;
long long w,f;
}tree[N<<];
struct Node
{
int x,y,z;
}node[N];
int cmp(Node a,Node b)
{
return a.y<b.y;
}
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
if(tree[k].l==tree[k].r)
{
tree[k].w=c;
return ;
}
;
build(k<<,l,mid);
build(k<<|,mid+,r);
tree[k].w=min(tree[k<<].w,tree[k<<|].w);
}
void down(int k)
{
tree[k<<].f+=tree[k].f;
tree[k<<|].f+=tree[k].f;
tree[k<<].w+=tree[k].f;
tree[k<<|].w+=tree[k].f;
tree[k].f=;
}
void change(int k)
{
if(tree[k].l>=a&&tree[k].r<=b)
{
tree[k].w+=x;
tree[k].f+=x;
return ;
}
if(tree[k].f) down(k);
;
);
|);
tree[k].w=min(tree[k<<].w,tree[k<<|].w);
}
void ask(int k)
{
if(tree[k].l>=a&&tree[k].r<=b)
{
minn=min(minn,tree[k].w);
return ;
}
if(tree[k].f) down(k);
;
);
|);
}
int main()
{
m=read(),n=read(),c=read();
build(,,n);
;i<=m;i++)
{
node[i].x=read(),node[i].y=read();
node[i].z=read();node[i].y--;
}
sort(node+,node++m,cmp);
;i<=m;i++)
{
a=node[i].x,b=node[i].y;
minn=);
),ans+=node[i].z;
),ans+=minn;
}
printf("%lld",ans);
}
AC代码
解谜游戏(puzzle)
Time Limit:1000ms Memory Limit:128MB
题目描述
LYK进了一家古董店,它很想买其中的一幅画。但它带的钱不够买这幅画。
幸运的是,老板正在研究一个问题,他表示如果LYK能帮他解出这个问题的话,就把这幅画送给它。
老板有一个n*m的矩阵,他想找一个和最大的子矩阵,这个子矩阵可以由四个参数x,y,x2,y2(1<=x<=x2<=n,1<=y<=y2<=m)来表示,表示一个左上角为(x,y),右下角为(x2,y2)的矩阵。
为了让游戏更加有趣,老板给了一个常数P,他想将原来这个矩阵中恰好一个数变为P,使得这个矩阵的最大的子矩阵尽可能大。
老板想知道这个最大值是多少。
你能帮帮LYK吗?
输入格式(puzzle.in)
第一行三个数n,m,P。
接下来n行,每行m个数ai,j描述整个矩阵。
输出格式(puzzle.out)
输出一个数表示答案。
输入样例
3 3 3
-100 3 3
3 -4 3
3 3 3
输出样例
20
样例解释
改变左上角那个数。
数据范围
对于20%的数据n,m<=10。
对于40%的数据n,m<=25。
对于60%的数据n,m<=50。
对于80%的数据n,m<=100。
对于100%的数据1<=n,m<=300,|P|,|ai,j|<=1000。
看到这个题,我们应该脑子里会蹦出这样的一个大水题吧:http://www.cnblogs.com/z360/p/7608115.html这是我们之前做过的·一道求最大矩形的题。
当时的这道题我们是这样做的:预处理出每一行的前缀和,然后暴力枚举矩形的上边界以及下边界,然后在枚举列,每当统计出的s出现负值,则说明出现了被吃掉的巧克力,更新s为0,然后在继续枚举。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 500
#define maxn 0x7fffffff
using namespace std;
long long n,m,s,x,y,a[N][N],sum[N][N],v1[N],v2[N],ans;
int main()
{
scanf("%lld%lld",&n,&m);
;i<=n;i++)
;j<=m;j++)
{
scanf("%lld",&a[i][j]);
if(!a[i][j])
a[i][j]=-maxn;
sum[i][j]+=sum[i-][j]+a[i][j];
}
;i<n;i++)
;j<=n;j++)
{
;k<=m;k++)
{
s+=sum[j][k]-sum[i][k];
) s=;
ans=max(ans,s);
}
s=;
}
printf("%lld",ans);
;
}
我们看着两个题的不同点,这个题我们要在这个矩形内改一个数来是这个矩形内的所有数的和变大,那么我们可以枚举将哪个点进行修改,N^2枚举需要进行修改的点,然后我们在采取上面的做法,我们就可以把N^5的得出答案。
我们考虑一下怎么进行优化,我们知道我们要讲一个矩形内的数进行修改的话,我们考虑修改呢个数对这个矩形造成的(负面)影响最小,即为是这个矩形尽可能地大,我们是不是就要找一个最小的数进行修改。那么我们可以预处理出每一个矩形内的最小值,以及每一个矩形内的所有数的和。然后我们N^4枚举一个矩形的左上角以及右下角,
(明明打了个60分的做法,但是由于题目意思理解的不是很透彻,然后wa掉了好几个点、、题目中说必须要改一个点的权值但是改的这个权值不一定要是我们选定的这个矩形,那么我们呢是不是就可以判断一下我们的最大的矩形是否为整个矩形,如果是整个矩形的话我们一定要改一个点,但是我们选出的这个矩形若不是整个矩形,我们可以改这个矩形以外的点也就是说我们可以将改与不改取一个max,这样应该就可以拿到60分)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 55
#define LL long long
using namespace std;
int n,m,p,a[N][N],minn[N][N][N][N],sum,ans,s[N][N][N][N];
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
int main()
{
freopen("puzzle.in","r",stdin);
freopen("puzzle.out","w",stdout);
n=read(),m=read(),p=read();
int m1,m2;
memset(minn,,sizeof(minn));
;i<=n;i++)
;j<=m;j++)
a[i][j]=read();
;h1<=n;h1++)
;l1<=m;l1++)
for(int h2=h1;h2<=n;h2++)
for(int l2=l1;l2<=m;l2++)
{
s[h1][l1][h2][l2]=s[h1][l1][h2-][l2]+s[h1][l1][h2][l2-]+a[h2][l2]-s[h1][l1][h2-][l2-];
m1=min(minn[h1][l1][h2-][l2-],a[h2][l2]),m2=min(minn[h1][l1][h2-][l2],minn[h1][l1][h2][l2-]);
minn[h1][l1][h2][l2]=min(m1,m2);
}
;h1<=n;h1++)
;l1<=m;l1++)
for(int h2=h1;h2<=n;h2++)
for(int l2=l1;l2<=m;l2++)
{
sum=s[h1][l1][h2][l2];
ans=max(ans,sum-minn[h1][l1][h2][l2]+p);
}
printf("%d",ans);
;
}
40分
唉,改过对题意理解不清的那个地方就是60分了,呜呜、、、
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 55
#define LL long long
using namespace std;
int n,m,p,a[N][N],minn[N][N][N][N],sum,ans,s[N][N][N][N];
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
int main()
{
n=read(),m=read(),p=read();
int m1,m2;
memset(minn,,sizeof(minn));
;i<=n;i++)
;j<=m;j++)
a[i][j]=read();
;h1<=n;h1++)
;l1<=m;l1++)
for(int h2=h1;h2<=n;h2++)
for(int l2=l1;l2<=m;l2++)
{
s[h1][l1][h2][l2]=s[h1][l1][h2-][l2]+s[h1][l1][h2][l2-]+a[h2][l2]-s[h1][l1][h2-][l2-];
m1=min(minn[h1][l1][h2-][l2-],a[h2][l2]),m2=min(minn[h1][l1][h2-][l2],minn[h1][l1][h2][l2-]);
minn[h1][l1][h2][l2]=min(m1,m2);
}
;h1<=n;h1++)
;l1<=m;l1++)
for(int h2=h1;h2<=n;h2++)
for(int l2=l1;l2<=m;l2++)
{
sum=s[h1][l1][h2][l2];
&&l1==&&h2==n&&l2==m)
ans=max(ans,sum-minn[h1][l1][h2][l2]+p);
else ans=max(ans,sum-minn[h1][l1][h2][l2]+max(p,minn[h1][l1][h2][l2]));
}
printf("%d",ans);
;
}
60分代码
我们再来看AC做法
老师讲解:枚举左上角 n^ 枚举右下角n^ 枚举修改的数 n^ 求和 n^ -> n^
求一个矩阵和,可以通过矩阵前缀和做到O()
枚举左上角 n^ 枚举右下角n^ 枚举修改的数 n^ -> n^
预处理出每个矩阵的最小值是多少。 n^
枚举左上角 n^ 枚举右下角n^ 修改的数已知(修改最小的或者不修改) -》n^
n,m<=
假如我们不要求修改数,查询最大子矩阵
有n个数,查询最大子段和 O(n)
; i<=n; i++) f[i]=max(f[i-]+a[i],a[i]);
max{f[i]} = 最大子段和
要求我们修改数
修改的数一定是最小的那个数。
f[i][]以i结尾并且没有数被修改过的最大和
f[i][]以i结尾并且有数被修改过的最大和 //a[i] 第i列的和
; i<=n; i++)
{
f[i][]=max(f[i-][]+a[i],a[i]);
f[i][]=max(f[i-][]+a[i],f[i-][]+a[i]-MIN[i]+P,a[i]-MIN[i]+P);
}
max{f[?][/]} 是答案
恰好改变一个数
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 305
using namespace std;
int n,m,p,ans,d[N],s[N][N],minn[N],a[N][N],dp[N][N];
int read()
{
,f=; char ch=getchar();
; ch=getchar();}
+ch-',ch=getchar();
return x*f;
}
int main()
{
n=read(),m=read(),p=read();
ans=-;//一定要记得赋初值
;i<=n;i++)
;j<=m;j++)
a[i][j]=read(),s[i][j]=s[i-][j]+a[i][j];//预处理前缀和
;i<=n;i++)//枚举上边界
{
;j<=m;j++) minn[j]=a[i][j];//预处理每一列里的最小值
for(int j=i;j<=n;j++)//枚举下边界
{
;k<=m;k++) minn[k]=min(minn[k],a[j][k]);//
;k<=m;k++) d[k]=s[j][k]-s[i-][k];//处理出在上边界与下边界围成的这个地方每一列的和
dp[][]=-;//赋初值
;k<=m;k++)
{
dp[k][]=max(dp[k-][]+d[k],d[k]);//dp[k][0]表示到k这一列还没有修改的情况 ,这种情况只能从两种状态转移过来,一种是他前面哪一行再加上这一行,还有一种是直接从这一行开始
dp[k][]=max(max(dp[k-][]+d[k],d[k]-minn[k]+p),dp[k-][]+d[k]-minn[k]+p);//dp[k][1]表示到k这一列已经修改了一个地方
} //这个有三种转移,一种是在这之前已经修改了然后再加上这一行,一种是直接从这一行开始那么要从这一行中选出一个数来进行修改,一种是在这一行之前没有修改过的要在这一行中选一个数进行修改
&&j==n)//判断是整个矩形的情况,那么这种情况下必须要在选出的这个矩形中修改一个数
ans=max(ans,dp[m][]);
else
;k<=m;k++) ans=max(ans,max(dp[k][],dp[k][]));//其他的情况下,我们可以从在我们选定的矩形中修改与不修改选一个大的
}
}
printf("%d",ans);
;
}
AC代码
10.1综合强化刷题 Day3的更多相关文章
- 10.1综合强化刷题 Day3 morning
竞赛时间:????年??月??日??:??-??:?? 题目名称 a b c 名称 a b c 输入 a.in b.in c.in 输出 a.out b.out c.out 每个测试点时限 1s 1s ...
- 10.1综合强化刷题 Day3 afternoon
竞赛时间:????年??月??日??:??-??:?? 题目名称 a b c 名称 a b c 输入 a.in b.in c.in 输出 a.out b.out c.out 每个测试点时限 1s 1s ...
- 10.1综合强化刷题 Day2 morning
一道图论神题(god) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图,只有 ...
- 10.1综合强化刷题 Day2 afternoon
最大值(max) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目: 这里有一个长度为n的 ...
- 10.1综合强化刷题 Day7
noip提高组模拟赛 ...
- 10.1综合强化刷题 Day1 afternoon
一道图论好题(graph) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一张无向图G={V,E},这张无向图有n个点m条边组成.并且这是一张带权图, ...
- 10.1综合强化刷题 Day6
T1 排序 题目描述 小Z 有一个数字序列a1; a2; .... ; an,长度为n,小Z 只有一个操作:选 定p(1<p<n),然后把ap 从序列中拿出,然后再插⼊到序列中任意位置. ...
- 10.1综合强化刷题 Day5
T1 拼不出的数 lost.in/.out/.cpp[问题描述]3 个元素的集合{5; 1; 2}的所有子集的和分别是0; 1; 2; 3; 5; 6; 7; 8.发现最小的不能由该集合子集拼出的数字 ...
- 10.1综合强化刷题 Day4
财富(treasure) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...
随机推荐
- HDU5952 Counting Cliques 暴搜优化
一.前言 这题看上去相当唬人(NPC问题),但是 因为限制了一些条件,所以实际上并没有太唬人. 二.题目 给你一个图,要求你找出数量为S的团的数量. 三.题解 暴搜,再加上一些玄学优化. 优化1:使用 ...
- (ADO.NET小知识点汇总)看到什么记什么
1.数据库连接池:在同时连接数不多的情况下, 打开一个链接往数据库导1W条数据的耗时 跟 导一条数据就打开跟关闭数据库连接的耗时 两者其实相差不大,这是为什么呢?打开关闭的本身不是有很多耗时吗?这是因 ...
- VBA连接到SQL2008需要加上端口号
VBA连接到SQL2008需要加上端口号1433,比如 conn = "server=XXXX.XXXX.XXXX.XXXX,1433;provider=SQLOLEDB.1;databas ...
- 8 REST Framework 实现Web API 1
1 参考博客: http://blog.csdn.net/SVALBARDKSY/article/details/50548073 2 准备工作 1. 环境 Python: Python 3.5 D ...
- loj2057 「TJOI / HEOI2016」游戏
记横联通是一块横着的没有硬石头的地,把他们编号.竖联通同理. 对于一个空地,将其横联通编号和竖联通编号连边,二分图匹配,最大匹配为答案. #include <iostream> #incl ...
- 了解JavaScript核心精髓(二)
1.字符串操作 //声明字符串 var str = "abcd"; var str = new String("abcd") //截取字符串 console.l ...
- uReplicator实现分析
MirrorMakerWorker分析 是整个同步机制的主入口,主要组织的逻辑有: 配置数据的传入与处理,ConsumerConfig对象的构建 度量对象的准备,定时上报的度量数据收集线程的定义与启动 ...
- 一些NGINX配置
一些nginx配置 使用独立目录, 然后include具体配置 gzip on for multi processers static file cache proxy pass 静态目录 or 文件 ...
- Linux常用命令与基本概念
复制 文件的复制 cp 源文件 目标文件 文件夹的复制 cp -r 源文件夹 目标文件夹 删除 删除文件 rm 文件名 删除文件夹 rm -rf 文件夹 查看文件类型 file 文件名 压缩与解压 z ...
- BZOJ 1787: [Ahoi2008]Meet 紧急集合(lca+贪心)
[Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 ...