怎么觉得天天都有模拟题啊QAQ
……T1T2我比大爷们写的都多了个log【2333
T1写完敲了个对拍,然而一拍就WA……搞了半天发现是暴力求lca写错了233333
……其实T1写了一个小时的原因是……正解十多分钟,暴力+datamaker十多分钟,……wa了找错+发现是暴力写错+改暴力……半个小时过去了233333
T1:
题意:n个节点的树,m次查询,求节点x和y之间的最长路径是否大于c【可以转换成这个意思……】
思路:…………我特么……写了个链剖序线段树233333,其实没有修改的话直接维护一下就好了……在不在同一条链上的时候,走的路径肯定是这条链的前缀,于是O(1)得到答案,最后那一节再用线段树瞎搞搞,单次查询是O(log(n))的,比起log方快到不知道哪里去了x
代码(O(n*log^2(n)))
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std; int n,m;
const long long INF = 0x3f3f3f3f3f3f3f3f;
struct t1{
int to,nxt,lth;
}edge[MAXN<<1]; int cnt_edge=0;
int fst[MAXN];
inline void addedge(int x,int y,int lth){
edge[++cnt_edge].to=y;
edge[cnt_edge].nxt=fst[x];
edge[cnt_edge].lth=lth;
fst[x]=cnt_edge;
edge[++cnt_edge].to=x;
edge[cnt_edge].nxt=fst[y];
edge[cnt_edge].lth=lth;
fst[y]=cnt_edge;
}
int root;
int fth[MAXN],top[MAXN],son[MAXN],siz[MAXN];
int dpt[MAXN];
int val[MAXN];
int dfn[MAXN],idf[MAXN],cnt_dfs=0;
void dfs1(int now){
siz[now]=1;
for(register int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
int aim=edge[tmp].to;
if(aim==fth[now]) continue;
fth[aim] = now;
dpt[aim] = dpt[now] + 1;
val[aim] = edge[tmp].lth;
dfs1(aim);
siz[now] += siz[aim];
if(siz[aim] >= siz[son[now]])
son[now] = aim;
}
}
void dfs2(int now,int tp){
top[now] = tp;
dfn[now] = ++cnt_dfs;
idf[cnt_dfs] = now;
if(son[now]) dfs2(son[now],tp);
for(register int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
int aim = edge[tmp].to;
if(aim == fth[now] || aim == son[now]) continue;
dfs2(aim,aim);
}
}
inline int lca(int u,int v){
while(top[u]^top[v])
(dpt[fth[top[u]]] < dpt[fth[top[v]]])?
v = fth[top[v]] : u = fth[top[u]];
return dpt[u]<dpt[v] ? u:v;
}
//===================================================================
int dt[MAXN<<2];
void build(int now,int l,int r){
if(l==r) return void(dt[now] = val[idf[l]]);
int mid = (l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
dt[now] = max(dt[now<<1],dt[now<<1|1]);
}
int inqry(int now,int l,int r,int L,int R){
if(L<=l&&r<=R)
return dt[now];
int mid=(l+r)>>1;
int tmp=0;
if(L<=mid) tmp=inqry(now<<1,l,mid,L,R);
if(mid<R) tmp = max(tmp,inqry(now<<1|1,mid+1,r,L,R));
return tmp;
}
int get_delta(int u,int v,int c){
int tmp = 0;
// printf("lca ( %d , %d ) = ",u,v);
while(top[u]^top[v]){
if( dpt[fth[top[u]]] < dpt[fth[top[v]]]){
tmp = max(tmp,inqry(1,1,n,dfn[top[v]],dfn[v]));
v = fth[top[v]];
}
else{
tmp = max(tmp,inqry(1,1,n,dfn[top[u]],dfn[u]));
u = fth[top[u]];
}
}
if(dpt[u] < dpt[v]) tmp = max(tmp,inqry(1,1,n,dfn[son[u]],dfn[v]));
else if(dpt[u] > dpt[v]) tmp = max(tmp,inqry(1,1,n,dfn[son[v]],dfn[u]));
// printf("%d\n",dpt[u]<dpt[v]?u:v);
return tmp-c;
}
//===============================================================================
long long ans=0;
int id=-1;
int read_x,read_y,read_c;
int main(){
srand(20000218);
freopen("rebuild.in","r",stdin);
freopen("rebuild.out","w",stdout);
scanf("%d%d",&n,&m);
if(!n) return puts("I'm angry!");
root = rand()%n+1;
for(register int i=1;i<n;++i)
scanf("%d%d%d",&read_x,&read_y,&read_c),addedge(read_x,read_y,read_c);
dpt[root]=1;
dfs1(root);
dfs2(root,root);
build(1,1,n);
for(register int i=1;i<=m;++i){
scanf("%d%d%d",&read_x,&read_y,&read_c);
int kk = get_delta(read_x,read_y,read_c);
if( kk > ans )
ans = kk,id=i;
// printf("id = %d dlt = %d\n",i,kk);
}
if(!~id) puts("I'm angry!");
else printf("%d",id);
return 0;
}
T2
题意:有个1到n的区间,m次操作,每次对(l,r)的区间增加一个数,只记录每个节点的前五个值
思路:……线段树套vector啊不怂……反正随便搞………………
然而大爷们怎么都跑得这么快QwQ
哦好嘛……嗯考虑一下,用链表维护这个序列,每次操作暴力地加上这个值,如果发现当前节点记录的值达到了5就直接从链表中删除这个点
于是每个节点最多被访问5次,均摊是O(n)的,常数是5
代码(O(n*log(n))的)
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std; int n,m;
struct t1{
int siz;
int rec[5];
void push(int x){rec[siz++]=x;}
t1():siz(0){rec[0]=rec[1]=rec[2]=rec[3]=rec[4]=0;}
};
t1 dt[MAXN<<2],tag[MAXN<<2];
inline void pushdown(int now){
for(int i=0;i<tag[now].siz;++i){
if(dt[now<<1].siz < 5)
dt[now<<1].push(tag[now].rec[i]),tag[now<<1].push(tag[now].rec[i]);
if(dt[now<<1|1].siz < 5)
dt[now<<1|1].push(tag[now].rec[i]),tag[now<<1|1].push(tag[now].rec[i]);
}
tag[now].siz=0;
}
void modify(int now,int l,int r,int L,int R,int v){
if(L<=l&&r<=R){
if(dt[now].siz>=5) return ;
dt[now].push(v);
tag[now].push(v);
return ;
}
int mid=(l+r)>>1;
pushdown(now);
if(L<=mid) modify(now<<1,l,mid,L,R,v);
if(mid<R) modify(now<<1|1,mid+1,r,L,R,v);
}
void print(int now,int l,int r){
if(l==r){
for(int i=0;i<dt[now].siz;++i)
printf("%d ",dt[now].rec[i]);
puts("");
return ;
}
pushdown(now);
int mid=(l+r)>>1;
print(now<<1,l,mid);
print(now<<1|1,mid+1,r);
}
int read_x,read_y;
int main(){
freopen("present.in","r",stdin);
freopen("present.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
scanf("%d%d",&read_x,&read_y);
modify(1,1,n,read_x,read_y,i);
}
print(1,1,n);
return 0;
}
T3
题面:………………德州扑克规则,(五十二张扑克牌去掉大小王)知道两个人的手牌和三张底牌,问赢的概率(平局算负)
思路:md模拟题,淦啊模拟题…………嗯上午哼着ギリギリEYE敲了10k代码发现还没写check……估计写完就是15k的量了23333
总之,这道题是只要写完不管多暴力都能过的那种23333
FTC大爷表示,每次枚举剩下的两张底牌,以及两个人选择的五张牌(相当于是枚举不选的那两张),然后check。
check的时候先按照每个值出现的次数排序,于是大部分情况被判掉了,同花这个直接判一下就好
代码:【woc我要死了我是谁我在哪儿……】
#include<bits/stdc++.h>
using namespace std; char read_s[5];
struct rec_card_num{
int cnt,num;
bool operator < (const rec_card_num ano) const{
return cnt==ano.cnt? num > ano.num : cnt > ano.cnt;
}
}rec[15];
struct card{
int col,num;
card(){}
card(int col,int num):col(col),num(num){}
card(char *s){
if((*s)=='S') col=0;
if((*s)=='H') col=1;
if((*s)=='D') col=2;
if((*s)=='C') col=3;
++s;
if(isdigit(*s)) num=*s-'0';
else{
if(*s=='T') num=10;
if(*s=='J') num=11;
if(*s=='Q') num=12;
if(*s=='A') num=14;
if(*s=='K') num=13;
}
}
bool operator < (const card ano)const{
return num==ano.num? col < ano.col: num < ano.num;
}
bool operator == (const card ano) const{
return col==ano.col && num==ano.num;
}
};
struct YJQ{
card c[7];
int rank,hash_val;
int tmp_rank,tmp_hash;
bool noo(card x){
for(int i=0;i<5;++i)
if(c[i]==x) return 0;
return 1;
}
card cur[5];
int cnt_cur;
void get_level_and_hash(){
for(int i=0;i<15;++i) rec[i].num=i,rec[i].cnt=0;
for(int i=0;i<5;++i)
++rec[cur[i].num].cnt;
sort(rec,rec+15);
if(rec[0].cnt==4){
tmp_rank = 3;
tmp_hash = rec[0].num * 15 + rec[1].num;
}
if(rec[0].cnt==3 && rec[1].cnt==2){
tmp_rank = 4;
tmp_hash = rec[0].num * 15 + rec[1].num;
}
if(rec[0].cnt==3 && rec[1].cnt==1){
tmp_rank = 7;
tmp_hash = rec[0].num * 15 * 15 + rec[1].num * 15 + rec[2].num;
}
if(rec[0].cnt==2 && rec[1].cnt==2){
tmp_rank = 8;
tmp_hash = rec[0].num * 15 * 15 + rec[1].num * 15 + rec[2].num;
}
if(rec[0].cnt==2 && rec[1].cnt==1){
tmp_rank = 9;
tmp_hash = rec[0].num * 15 * 15 * 15
+ rec[1].num * 15 * 15
+ rec[2].num * 15
+ rec[3].num ;
}
if(rec[0].cnt==1){
int tong = 1;
for(int i=1;i<5;++i)
if(cur[i].col ^ cur[0].col)
tong = 0;
int shun = 1;
for(int i=0;i<4;++i)
if(rec[i+1].num ^ (rec[i].num-1))
shun=0;
if(rec[0].num==14 && rec[1].num==5 && rec[2].num==4 &&
rec[3].num==3 &&rec[4].num==2)
shun=1;
if(shun){
tmp_rank = tong ? 2 : 6 ;
tmp_hash = (rec[0].num==14 && rec[1].num==5)?5:rec[0].num;
}
else{
tmp_rank = tong ? 5 : 10;
tmp_hash = rec[0].num * 15 * 15 * 15 * 15
+ rec[1].num * 15 * 15 * 15
+ rec[2].num * 15 * 15
+ rec[3].num * 15
+ rec[4].num ;
}
}
}
void get_max(){
for(int i=0;i<7;++i)
for(int j=i+1;j<7;++j){
cnt_cur=0;
for(int k=0;k<7;++k)
if((k^i)&&(k^j))
cur[cnt_cur++]=c[k];
get_level_and_hash();
if(tmp_rank < rank){
rank = tmp_rank;
hash_val = tmp_hash;
}
else{
if(tmp_rank == rank){
if( tmp_hash > hash_val)
hash_val = tmp_hash;
}
}
}
}
void print(){
for(int i=0;i<7;++i)
printf("col = %d num = %d\n",c[i].col,c[i].num);
puts("");
}
}fr,wa;
int main(){
freopen("interview.in","r",stdin);
freopen("interview.out","w",stdout);
scanf("%s",read_s);
while(read_s[0]^'#'){
fr.c[0]=card(read_s);
scanf("%s",read_s);
fr.c[1]=card(read_s);
scanf("%s",read_s);
wa.c[0]=card(read_s);
scanf("%s",read_s);
wa.c[1]=card(read_s);
scanf("%s",read_s);
fr.c[2]=wa.c[2]=card(read_s);
scanf("%s",read_s);
fr.c[3]=wa.c[3]=card(read_s);
scanf("%s",read_s);
fr.c[4]=wa.c[4]=card(read_s);
int shang = 0,xia = 0;
for(int xi=0;xi<4;++xi)
for(int xj=2;xj<=14;++xj)
for(int yi=0;yi<4;++yi)
for(int yj=2;yj<=14;++yj){
card x(xi,xj),y(yi,yj);
if(x < y && fr.noo(x) && fr.noo(y) && wa.noo(x) && wa.noo(y)){
fr.c[5]=wa.c[5]=x;
fr.c[6]=wa.c[6]=y;
++xia;
fr.rank=11,wa.rank=11;
fr.get_max();
wa.get_max();
// printf("rank zhangzhe = %d\n",fr.rank);
// printf("rank wallace = %d\n",wa.rank);
if(fr.rank < wa.rank){
++shang;
// printf("%d\n",xia);
// puts("HA");
// fr.print();
// puts("WA");
// wa.print();
}
else{
if(fr.rank == wa.rank)
if(fr.hash_val > wa.hash_val){
++shang;
// printf("%d\n",xia);
// puts("HA");
// fr.print();
// puts("WA");
// wa.print();
}
}
}
}
printf("%.3f\n",(double)shang/xia);
scanf("%s",read_s);
}
}