排位Round2补题报告
T1
克鲁斯卡尔跑完最小生成树,把选中边放到edg里面,接着跑树链剖分的两遍DFS,建一颗线段树,直接查最小值就行了。
注意是边权线段树,权值放在深度打的点上。
还有就是查询的ID就是她本来的ID,用newid边查边错。
一开始心情爆炸没时间写这题了,其·实挺裸的。
#include <bits/stdc++.h>
#define nmax 200050
#define inf 1000000050
using namespace std;
int father[nmax];
int rnk[nmax];
struct myx{
int form,to,val;
int id;
bool ischoosen;
}my[nmax];
struct edge{
int to,next;
}edg[nmax<<2];
struct you{
int from,to,val;
}you[nmax];
struct tree{
int l,r,val;
int mid(){
return (l+r)>>1;
}
}tree[nmax<<2];
int fa[nmax],son[nmax],sz[nmax],newid[nmax],hashback[nmax],dep[nmax],top[nmax];
int head[nmax],val;
int tot =0,num = 0;
int n,m;
void add(int u, int v){
edg[tot].to = v;
edg[tot].next = head[u];
head[u] = tot++;
}
int findset(int x){
int r = x,temp;
while(father[r] != r) r = father[r];
while(x != r){
temp = father[x];
father[x] = r;
x = temp;
}
return r;
}
void unionset(int x, int y){
x = findset(x);
y = findset(y);
if(x == y) return;
if(rnk[x] > rnk[y]){
father[y] = x;
}else{
father[x] = y;
if(rnk[x] == rnk[y])
rnk[x] ++;
}
}
bool cmp(myx a,myx b){
if(a.val < b.val) return true;
else return false;
}
void kelusikaer(){
for(int i = 0;i<m;++i){
int x = findset(my[i].form);
int y = findset(my[i].to);
if(x != y){
you[++num].from = my[i].form;
you[num].to = my[i].to;
you[num].val = my[i].val;
add(my[i].form,my[i].to);
add(my[i].to,my[i].form);
unionset(my[i].form,my[i].to);
my[i].ischoosen = true;
}
}
}
void dfsFirst(int rt, int f,int d){
dep[rt] = d;
fa[rt] = f;
sz[rt] = 1;
for(int i = head[rt]; i!= -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != f){
dfsFirst(nxt,rt,d+1);
sz[rt]+=sz[nxt];
if(son[rt] == -1 || sz[nxt] > sz[son[rt]]){
son[rt] = nxt;
}
}
}
}
void dfsSecond(int rt, int tp){
top[rt] = tp;
newid[rt] = ++num;
if(son[rt] == -1) return;
dfsSecond(son[rt],tp);
for(int i = head[rt];i != -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != son[rt] && nxt != fa[rt])
dfsSecond(nxt,nxt);
}
}
void PushUp(int rt){
tree[rt].val = min(tree[rt<<1].val , tree[rt<<1|1].val);
}
void Build(int l, int r, int rt){
tree[rt].l = l; tree[rt].r = r;
if(l == r){
return;
}
Build(l,tree[rt].mid(),rt<<1);
Build(tree[rt].mid()+1,r,rt<<1|1);
PushUp(rt);
}
void UpdatePoint(int val, int pos, int rt){
if(tree[rt].l == tree[rt].r){
tree[rt].val = val ;
return;
}
if(pos <= tree[rt].mid()) UpdatePoint(val,pos,rt<<1);
else UpdatePoint(val,pos,rt<<1|1);
PushUp(rt);
}
int QueryMIN(int l,int r,int rt){
if(l <= tree[rt].l && tree[rt].r <= r) return tree[rt].val;
int ans = inf;
if(l <= tree[rt].mid()) ans = min(ans,QueryMIN(l,r,rt<<1));
if(r > tree[rt].mid()) ans = min(ans,QueryMIN(l,r,rt<<1|1));
return ans;
}
int Find_MIN(int x, int y){
int tx = top[x],ty =top[y];
int ans = inf;
while(tx != ty){
if(dep[tx] < dep[ty]){
swap(x,y);
swap(tx,ty);
}
ans = min (QueryMIN(newid[tx],newid[x],1),ans);
x = fa[tx]; tx = top[x];
}
if(x == y) return ans;
if(dep[x] > dep[y]) swap(x,y);
ans = min( QueryMIN(newid[son[x]],newid[y],1),ans);
return ans;
}
bool cmp2(myx a, myx b){
if(a.id < b.id) return true;
else return false;
}
void init(){
memset(tree,0,sizeof tree);
memset(head,-1,sizeof head);
memset(son,-1,sizeof son);
memset(edg,0,sizeof edg);
memset(hashback,0,sizeof hashback);
memset(my,0,sizeof my);
memset(you,0,sizeof you);
tot = num = 0;
}
int main()
{
// freopen("in.txt","r",stdin);
while(scanf("%d %d",&n,&m) != EOF){
init();
for(int i = 1;i<n;++i) father[i] = i,rnk[i] = 0;
for(int i = 0;i<m;++i) scanf("%d %d %d",&my[i].form,&my[i].to,&my[i].val),my[i].id = i;
sort(my,my+m,cmp);
kelusikaer();
num = 0;
dfsFirst(1,0,1);
dfsSecond(1,1);
Build(1,n,1);
for(int i = 1;i<=num-1;++i){
if(dep[you[i].from] > dep[you[i].to]) swap(you[i].from,you[i].to);
UpdatePoint(you[i].val,newid[you[i].to],1);
}
sort(my,my+m,cmp2);
for(int i = 0;i<m; ++i){
int x = my[i].form;
int y = my[i].to;
if(my[i].ischoosen){
printf("Ohyee\n");
}else{
printf("%d\n",Find_MIN(x,y));
}
}
}
return 0;
}
T2
水,一开始还想直接用int读?,我真天真。
#include <bits/stdc++.h>
#define nmax 1000000
#define ll long long
using namespace std;
char str[nmax];
void convertToNum(int tag1,int tag2,int & ans){
int base = 1;
ans = 0;
for(int i = tag2;i>=tag1;i--){
ans += (str[i] -'0') *base;
base*=10;
}
}
int main()
{
int a,b,c;
char op,equ;
ll ans;
while(scanf("%s",str) != EOF){
int len = strlen(str);
int tag1 ,tag2,tag3,tag4,tag5;
tag1 = 0;
int type = 0;
bool opisfound = false;
bool equuisfound = false;
for(int i= 0;i<len;++i){
if(str[i] == '+' || str[i] == '-'){
op = str[i];
tag2 = i-1;
tag3 = i+1;
opisfound = true;
}else if(str[i] == '='){
tag4 = i-1;
tag5 = i+1;
equuisfound = true;
}
if(str[i] == '?'){
if(!opisfound && !equuisfound) type = 1;
else if(opisfound && !equuisfound ) type = 2;
else type = 3;
}
}
if(type == 1){
convertToNum(tag3,tag4,b);
convertToNum(tag5,len-1,c);
if(op == '+') ans = c - b;
else ans = b+c;
}else if(type == 2){
convertToNum(tag1,tag2,a);
convertToNum(tag5,len-1,c);
if(op == '+') ans = c- a;
else ans = a- c;
}else{
convertToNum(tag1,tag2,a);
convertToNum(tag3,tag4,b);
if(op == '+') ans = a+b;
else ans = a-b;
}
printf("%lld\n",ans);
}
return 0;
}
T3
贪心水,错了几发贡献罚时。
#include <bits/stdc++.h>
#define nmax 5050
#define ll long long
using namespace std;
int n;
ll total;
struct ite{
ll price;
ll num;
}item[nmax];
bool cmp(ite a, ite b){
if(a.price < b.price) return true;
else return false;
}
int main()
{
while(scanf("%lld %d",&total,&n) != EOF){
for(int i = 0;i<n;++i){
scanf("%lld %lld",&item[i].price,&item[i].num);
}
sort(item,item+n,cmp);
ll ans = 0;
for(int i = 0;i<n;++i){
if(total >= item[i].num){
ans += item[i].num * item[i].price;
total -= item[i].num;
if(total == 0) break;
}else{
ans += total * item[i].price;
total = 0;
break;
}
}
printf("%lld\n",ans);
}
return 0;
}
T4
手推Fib数列,然后秒。
#include <bits/stdc++.h>
#define nmax 1000100
#define MOD 1000000007
using namespace std;
int a[nmax];
void init(){
a[1] = 1;
a[2] = 2;
a[3] = 3;
for(int i = 4;i<=1000000;++i){
a[i] = (a[i-1] + a[i-2]) % MOD;
}
}
int main()
{
int n;
init();
while(scanf("%d",&n) != EOF){
printf("%d\n",a[n]);
}
return 0;
}
T5
树上骚操作,发现能贡献答案的也就2种结构,维护每个节点SIZE即可,写完调了一会就出来,也是没时间写了。
#include <bits/stdc++.h>
#define ll long long
#define nmax 200820
using namespace std;
int fa[nmax],son[nmax],sz[nmax],newid[nmax],dep[nmax],newout[nmax],newid2[nmax];
int num,tot,head[nmax];
int minu[nmax];
struct edge{
int to;
int next;
}edg[nmax<<2];
struct tre{
int l,r;
ll val,lazy;
int mid(){
return (l+r)>>1;
}
}tree[nmax<<2];
void add(int u, int v){
edg[tot].to = v;
edg[tot].next = head[u];
head[u] = tot++;
}
void dfsFirst(int rt, int f,int d){
dep[rt] = d;
fa[rt] = f;
sz[rt] = 1;
for(int i = head[rt]; i!= -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != f){
dfsFirst(nxt,rt,d+1);
sz[rt]+=sz[nxt];
if(son[rt] == -1 || sz[nxt] > sz[son[rt]]){
son[rt] = nxt;
}
}
}
}
void dfsSecond(int rt, int tp){
newid[rt] = ++num;
if(son[rt] == -1){
newid2[rt] = num;
return;
}
dfsSecond(son[rt],tp);
for(int i = head[rt];i != -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != son[rt] && nxt != fa[rt])
dfsSecond(nxt,nxt);
}
newid2[rt] = num;
}
void init(){
memset(head,-1,sizeof head);
memset(son,-1,sizeof son);
tot = num = 0;
}
int ans = 0;
void dfs(int rt,int f){
if(sz[rt] == 2){
minu[rt] = sz[rt];
ans++;return;
}else if(sz[rt] >= 3){
int times = sz[rt] - 1;
for(int i = head[rt]; i!= -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != f && sz[nxt] == 1){
times--;
}
}
if(times == 0){
ans++;
minu[rt] = sz[rt];
return;
}
}
for(int i = head[rt]; i!= -1; i = edg[i].next){
int nxt = edg[i].to;
if(nxt != f && sz[nxt] >=2){
dfs(nxt,rt);
minu[rt] += minu[nxt];
}
}
sz[rt] -= minu[rt];
if(sz[rt] == 2){
minu[rt] += sz[rt];
ans++;
}else if(sz[rt] >= 3){
int i = head[rt];
int nxt = edg[i].to;
int ip = edg[i].next;
int nxtp = edg[ip].to;
if( (nxt!=f && nxt !=-1) && (nxtp !=f && nxtp != -1)){
ans++;
minu[rt] += sz[rt];
}
}
}
int n,m;
int main()
{
while(scanf("%d",&n)!=EOF){
init();
int u,v,x,y;
for(int i =1;i<=n-1;++i){
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfsFirst(1,0,1);
dfsSecond(1,1);
dfs(1,0);
printf("%d\n",ans);
}
return 0;
}
T6
QAQ
T7
本场比赛最坑的题没有之一,板子上面的判断有问题,我一直以为是算法有问题。其实就是一个高精度进制转换,T到心态爆炸。
比赛有风险啊。
#include<bits/stdc++.h>
#define nmax 80000000
using namespace std;
int ans[nmax];
char str[nmax];
char temp[nmax];
int pos = 0;
void div(int b)
{
int d=0;
int len = strlen(str);
int temppos= 0;
while(strcmp(str,"0")!=0){
d = 0;
temppos = 0;
for(int i=0;i<len;i++){
temp[temppos++]=(d*10+str[i]-'0')/b+'0';
d=(d*10+(str[i]-'0'))%b;
}
ans[pos++] = d;
int p=0;
for(int i=0;i<temppos;i++)
if(temp[i]!='0') {p=i;break;}
temp[temppos] = '\0';
strcpy(str,temp+p);
len = temppos-p;
if(str[0] == '0' || str[0] == '\0') break;
}
}
int main()
{
int b;
while(scanf("%s",str) != EOF){
scanf("%d",&b);pos = 0;div(b);
for(int i = pos-1;i>=0;--i) printf("%d\n",ans[i]);
}
return 0;
}