TJOI2014
匹配
给出一个\(n(n\leq80)\)个点对\(n\)个点的带权二分图,求所有最大权匹配的交集。
先求出一个最大权匹配,然后枚举每一条匹配中的边,检验删除该边后是否还能形成最大权匹配。如果能则说明该边不在交集中,否则一定在交集中。
电源插排
一个长度为\(n(n\leq10^9)\)的插排,初始时是空的。进行\(Q(Q\leq10^5)\)次操作,操作有三种:
- 向整个插排上最大的空区间(相等取最右)的中间(也取右)插上一个插头\(x\)。
- 询问区间\([L,R]\)中有几个插头。
- 拔出插头\(x\)。
用动态开点线段树来做即可。每条线段维护四个值:左起最长空区间的右端点,区间最长空区间的左、右端点,右起最长空区间的左端点。再记录一下插头\(x\)的位置就可以删除啦。
拼图
给出\(n(n\leq16)\)块四连通碎片,求有多少种方案将他们一起拼成一个\(4\times4\)的正方形。若没有,输出No Solution
;只有一种,输出Yes, only one!
和这个方案;否则输出Yes, many!
。
似乎直接爆搜即可,优化一点可以按块由大到小搜索,再优化可以搞搞状压什么的。
上升子序列
给出一个\(n(n\leq10^5)\)长度的数列,求该数列有多少个不同的长度至少为\(2\)的上升子序列,答案对\(10^9+7\)取模。两个子序列\(a,b\)被认为不同当且仅当\(\exists i,a_i \neq b_i\)。
记录\(cnt[i]\)表示目前以数字\(i\)为结尾的不同上升子序列有多少个。当做到\(a_i\)时,\(cnt[a_i]\)变为\(1+\sum_{i=1}^{a[i]-1}cnt[i]\)个,额外的\(1\)表示只有一个数的序列\(\{a_i\}\),求和表示\(a_i\)能够接在多少个上升子序列后。要注意\(cnt[a_i]\)是变为,而不是加上,因为如果存在\(a_{i'}=a_i(i'<i)\),那么以\(a_{i'}\)结尾的上升子序列一定出现在以\(a_i\)结尾的上升子序列中(把原序列中的\(a_{i'}\)换成\(a_i\))。
那么我们需要支持单点修改和前缀求和,可以用树状数组解决。
Alice and Bob
对于序列\(\{x_n\}(n\leq10^5)\),记\(a_i\)表示以\(x_i\)结尾的最长上升子序列长度,\(b_i\)表示以\(x_i\)开头的最长下降子序列长度。给出\({a_n}\),求\(\sum_{i=1}^nb_i\)的最大值。
若在\(a_1..a_{i-1}\)中有\(k\)个大于\(a_i\),那么说明在\(x_1..x_{i-1}\)中,至少有\(k\)个大于\(x_i\),至少有\(a_i-1\)个小于\(x_i\)。
我没太看懂的题解:现在我们已知了一些大小关系。对于未知的关系,我们默认左边大于右边。构造序列并求\(\sum_{i=1}^nb_i\)即可。
电影评分
搞一个电影评分系统,进行\(n(n\leq10^4)\)次操作,操作有三种:
- 发布一部编号为\(ID\)的电影,有\(x(x\leq5)\)个主演\(\{actor_x\}\),其评分为与其有共同主演的最新电影的评分,若没有则为\(0\)。
- 查询排名为\(x\)的电影的编号。排名以评分为第一关键字,发布时间为第二关键字。
- 将电影\(ID\)的评分调整为原评分与\(x\)的平均数。
题解:将题目中的分数分为整数部分和小数部分,将小数部分写成二进制形式,此时可以使用后缀平衡树维护小数之间的大小关系。将小数部分和整数部分结合即可比较分数的大小关系。没大看懂,也不会后缀平衡树。
Code
//匹配
#include <cstdio>
#include <cstring>
#include <queue>
int const N=300;
int const INF=0x3F3F3F3F;
int min(int x,int y) {return x<y?x:y;}
int n;
int h[N],cnt;
struct edge{int u,v,c,w,nxt;} ed[N*N];
void edAdd(int u,int v,int c,int w)
{
cnt++; ed[cnt].u=u,ed[cnt].v=v,ed[cnt].c=c,ed[cnt].w=w,ed[cnt].nxt=h[u],h[u]=cnt;
cnt++; ed[cnt].u=v,ed[cnt].v=u,ed[cnt].c=0,ed[cnt].w=-w,ed[cnt].nxt=h[v],h[v]=cnt;
}
int s,t;
int dst[N],path[N];
std::queue<int> Q; bool inQ[N];
void clear() {for(int i=2;i<=cnt;i++) ed[i].c=i&1?0:ed[i].c+ed[i^1].c;}
bool SPFA()
{
for(int u=s;u<=t;u++) dst[u]=-INF,path[u]=0;
memset(inQ,false,sizeof inQ);
dst[s]=0; Q.push(s),inQ[s]=true;
while(!Q.empty())
{
int u=Q.front(); Q.pop(),inQ[u]=false;
for(int i=h[u];i;i=ed[i].nxt)
{
int v=ed[i].v,w=ed[i].w;
if(ed[i].c&&dst[u]+w>dst[v])
{
dst[v]=dst[u]+w,path[v]=i;
if(!inQ[v]) Q.push(v),inQ[v]=true;
}
}
}
return dst[t]>-INF;
}
int maxFl()
{
int cost=0;
while(SPFA())
{
int fl=INF;
for(int i=path[t];i;i=path[ed[i^1].v]) fl=min(fl,ed[i].c);
for(int i=path[t];i;i=path[ed[i^1].v]) ed[i].c-=fl,ed[i^1].c+=fl;
cost+=fl*dst[t];
}
return cost;
}
int cntM,M[N];
int main()
{
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
scanf("%d",&n);
s=0,t=n+n+1; cnt=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) {int x; scanf("%d",&x); edAdd(i,n+j,1,x);}
for(int i=1;i<=n;i++) edAdd(s,i,1,0),edAdd(n+i,t,1,0);
int ans=maxFl(); printf("%d\n",ans);
cntM=0;
for(int u=1;u<=n;u++)
for(int i=h[u];i;i=ed[i].nxt) if(!ed[i].c&&ed[i].v!=s) M[++cntM]=i;
for(int k=1;k<=cntM;k++)
{
clear(),ed[M[k]].c=0;
int cost=maxFl();
ed[M[k]].c=1;
if(cost<ans) printf("%d %d\n",ed[M[k]].u,ed[M[k]].v-n);
}
return 0;
}
//电源插排
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
inline char gc()
{
static char now[1<<16],*S,*T;
if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
return *S++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
int const Q=1e5+10;
int n,q; map<int,int> pos;
#define s sg[s0]
int rt,sgCnt;
struct seg{int eptL0,eptR0,eptL,eptR,sum; int Lc,Rc;} sg[40*Q];
void create(int s0,int L0,int R0) {s.eptL0=s.eptR=R0,s.eptR0=s.eptL=L0,s.sum=0;}
void update(int s0,int L0,int R0)
{
int mid=L0+R0>>1; seg Ls=sg[s.Lc],Rs=sg[s.Rc];
s.eptL0=Ls.eptL0; if(Ls.eptL0==mid) s.eptL0=Rs.eptL0;
s.eptR0=Rs.eptR0; if(Rs.eptR0==mid+1) s.eptR0=Ls.eptR0;
int len1=Ls.eptR-Ls.eptL+1,len2=Rs.eptL0-Ls.eptR0+1,len3=Rs.eptR-Rs.eptL+1;
int mx=max(len2,max(len1,len3));
if(len3==mx) s.eptL=Rs.eptL,s.eptR=Rs.eptR;
else if(len2==mx) s.eptL=Ls.eptR0,s.eptR=Rs.eptL0;
else if(len1==mx) s.eptL=Ls.eptL,s.eptR=Ls.eptR;
s.sum=Ls.sum+Rs.sum;
}
int L,R;
void add(int s0,int L0,int R0,int v)
{
if(L<=L0&&R0<=R)
{
s.sum=v;
if(v==1) s.eptL0=L0-1,s.eptR0=R0+1,s.eptL=L0+1,s.eptR=L0;
else s.eptL0=s.eptR0=s.eptL=s.eptR=L0;
return;
}
int mid=L0+R0>>1;
if(!s.Lc) create(s.Lc=++sgCnt,L0,mid);
if(!s.Rc) create(s.Rc=++sgCnt,mid+1,R0);
if(L<=mid) add(s.Lc,L0,mid,v); if(mid<R) add(s.Rc,mid+1,R0,v);
update(s0,L0,R0);
}
int query(int s0,int L0,int R0)
{
if(s0==0) return 0;
if(L<=L0&&R0<=R) return s.sum;
int mid=L0+R0>>1; int res=0;
if(L<=mid) res+=query(s.Lc,L0,mid);
if(mid<R) res+=query(s.Rc,mid+1,R0);
return res;
}
int main()
{
freopen("switch.in","r",stdin);
freopen("switch.out","w",stdout);
n=read(),q=read();
create(rt=++sgCnt,1,n);
for(int i=1;i<=q;i++)
{
int k=read();
if(k==0) {L=read(),R=read(); printf("%d\n",query(rt,1,n));}
else
{
L=R=(sg[rt].eptL+sg[rt].eptR-1)/2+1;
if(pos[k]) L=R=pos[k],add(rt,1,n,0),pos[k]=0;
else add(rt,1,n,1),pos[k]=L;
}
}
return 0;
}
//上升子序列
#include <cstdio>
#include <algorithm>
using namespace std;
int const N=1e5+10;
int const H=1e9+7;
int n,a[N]; int n0,map[N];
int tr[N];
void add(int x,int v) {while(x<=n0) tr[x]=(tr[x]+v)%H,x+=x&(-x);}
int sum(int x) {int res=0; while(x) res=(res+tr[x])%H,x-=x&(-x); return res;}
int pre[N];
int main()
{
freopen("subsequence.in","r",stdin);
freopen("subsequence.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),map[i]=a[i];
sort(map+1,map+n+1); n0=unique(map+1,map+n+1)-(map+1);
for(int i=1;i<=n;i++) a[i]=lower_bound(map+1,map+n0+1,a[i])-map;
for(int i=1;i<=n0;i++) pre[i]=0;
for(int i=1;i<=n;i++)
{
int res=sum(a[i]-1)+1;
add(a[i],res-pre[a[i]]); pre[a[i]]=res;
}
printf("%d\n",sum(n0)-n0);
return 0;
}
TJOI2014的更多相关文章
- P3968 [TJOI2014]电源插排
P3968 [TJOI2014]电源插排 线段树维护最长空区间及左端点位置,这个和$nlongn$的动态最大子序和差不多,就不多解释了 $n$较大哈希优化空间 My complete code: #i ...
- bzoj5157: [Tjoi2014]上升子序列(树状数组LIS)
5157: [Tjoi2014]上升子序列 题目:传送门 题解: 学一下nlogn的树状数组求最长上生子序列就ok(%爆大佬) 离散化之后,用一个数组记录一下,直接树状数组做 吐槽:妈耶...一开始不 ...
- [TJOI2014]拼图
嘟嘟嘟 一眼看上去像状压dp,然后越想复杂度越不对劲,最后发现和爆搜差不多,索性就写爆搜了,复杂度\(O(\)能过\()\). 别忘了填拼图和回溯的时候只动拼图中是1的部分,不要把\(n * m\)的 ...
- [TJOI2014]Alice and Bob[拓扑排序+贪心]
题意 给出一个序列的以每一项结尾的 \(LIS\) 的长度a[],求一个序列,使得以每一项为开头的最长下降子序列的长度之和最大. \(n\leq 10^5\) . 分析 最优解一定是一个排列,因为如果 ...
- [BZOJ 5155][Tjoi2014]电源插排
传送门 网上大部分题解都写得是动态开点线段树,然而像\(MiEcoku\)这么懒惰的显然不会去写线段树... \(\color{green}{solution}\) 我们考虑来点骚操作. 线段树维护的 ...
- 【bzoj5157】[Tjoi2014]上升子序列 树状数组
题目描述 求一个数列本质不同的至少含有两个元素的上升子序列数目模10^9+7的结果. 题解 树状数组 傻逼题,离散化后直接使用树状数组统计即可.由于要求本质不同,因此一个数要减去它前一次出现时的贡献( ...
- [BZOJ 5158][Tjoi2014]Alice and Bob
传送门 \(\color{green}{solution}\) 贪心 /************************************************************** P ...
- 【[TJOI2014]上升子序列】
这本质上是一个\(dp\) 如果没有"两个上升子序列相同,那么只需要计算一次"这一个性质,那么就很好做了,我们用\(dp[i]\)表示以\(i\)结尾的上升子序列个数,那么就有\( ...
- vijos1859[TJOI2014]电源插排
题意:小 M 的实验室有很多电源插排.这些插排的编号从 1 到 N,由左向右排成一排.每天早晨,这些插排都是没有被使用的.每当一个学生来到实验室,他就将自己的笔记本电源插到某一个未被使用的插排上.实验 ...
- 【刷题】BZOJ 5154 [Tjoi2014]匹配
Description 有N个单身的男孩和N个单身女孩,男孩i和女孩j在一起得到的幸福值为Hij.一个匹配即对这N个男孩女孩的安排: 每个男孩恰好有一个女朋友,每个女孩恰好有一个男朋友.一个匹配的幸福 ...
随机推荐
- Design Patterns Uncovered: The Chain Of Responsibility Pattern
Chain of Responsibility in the Real World The idea of the Chain Of Responsibility is that it avoids ...
- Json和序列化总结
一.序言 遇到问题,就经常逛园,不知你是否曾有,曾经遇到的问题,或者在园子里看到问题的方案,过一段时间,有可能还会摔跤,哈哈...大神请勿喷,小弟记忆不太好,还过来找资料,如果自己写把问题或某个知识点 ...
- AJPFX实现兔子问题
有一对小兔子,从第三个月长成开始每个月生一对小兔子,新出生的小兔子从第三个月长成开始每个月也生一对小兔子,假设所有的兔子都不会死,问每个月兔子的总数?(月数可以是6,12).大神看看我笨方法谢的对吗? ...
- 【转】JobScheduler
JobScheduler JobScheduler是Android L(API21)新增的特性,用于定义满足某些条件下执行的任务.它的宗旨是把一些不是特别紧急的任务放到更合适的时机批量处理,这样可以有 ...
- pandas中loc-iloc-ix的使用
转自:https://www.jianshu.com/p/d6a9845a0a34 Pandas中loc,iloc,ix的使用 使用 iloc 从DataFrame中筛选数据 iloc 是基于“位置” ...
- ios https 安全证书配置
原定于2017年1月1日起所有提交到 App Store 的App必须强制开启 ATS,需要配置Https.但是现在不需要了,无固定期限的往后延期了,但是这个还是得弄明白下为好,说不定哪天突然就让弄了 ...
- iOS Getter 和Setter 注册xibcell
// 初始化cell的xib的方式 [tableView registerNib:[UINib nibWithNibName:@"LXmiddleCell" bundle:nil] ...
- 读取Chrome书签文件
使用C#读取Chrome浏览器的本地书签文件,当前文件在C盘下用户文件夹\AppData\Local\Google\Chrome\User Data\Default\下的Bookmarks 打开这个文 ...
- sql地址寻路算法(省市区路)
最近无意翻开4年前做过的一个功能,就是搜集全国各城市各个区(县)的路(XX路.XX道.XX街.XX镇.XX乡.XX屯.XX村.XX社).众所周知,我们都可以在网上找到省.市.区(县)这三级联动的数据, ...
- Android(java)学习笔记178:多媒体之计算机图形表示方式
1. 多媒体 很多媒体:文字(TextView,简单不讲),图片,声音,视频等等. 2. 图片 计算机如何表示图片的? (1)bmp 高质量保存 256色位图:图片中的每个像素点可以有256 ...