报同步赛的时候出了些意外。于是仅仅能做一做“滞后赛”了2333

DAY1

T1离线+离散化搞,对于相等的部分直接并查集,不等部分查看是否在同一并查集中就可以,code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n;
int father[200001];
struct hp{
int kind,x,y;
bool operator < (const hp &a) const
{return kind>a.kind;}
}qst[200001];
int b[400001];
int find(int x)
{
if (x!=father[x])
father[x]=find(father[x]);
return father[x];
}
int main()
{
int i,st,r1,r2,size;
bool f;
freopen("prog.in","r",stdin);
freopen("prog.out","w",stdout);
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
for (i=1;i<=n;++i)
{
scanf("%d%d%d",&qst[i].x,&qst[i].y,&qst[i].kind);
b[i*2-1]=qst[i].x; b[i*2]=qst[i].y;
}
sort(b+1,b+2*n+1);
size=unique(b+1,b+2*n+1)-b-1;
for (i=1;i<=n;++i)
{
qst[i].x=upper_bound(b+1,b+size+1,qst[i].x)-b-1;
qst[i].y=upper_bound(b+1,b+size+1,qst[i].y)-b-1;
}
sort(qst+1,qst+n+1);
for (i=1;i<=size;++i)
father[i]=i;
st=n+1;
for (i=1;i<=n;++i)
{
if (qst[i].kind==0) {st=i; break;}
r1=find(qst[i].x);
r2=find(qst[i].y);
if (r1!=r2) father[r1]=r2;
}
f=false;
for (i=st;i<=n;++i)
{
r1=find(qst[i].x);
r2=find(qst[i].y);
if (r1==r2) {f=true; break;}
}
if (f) printf("NO\n");
else printf("YES\n");
}
}

T2裸链剖啊。同【HAOI 2015】T2,对于子树问题能够在建树的时候记录一下子树的左右边界。(据说这题现场200+人AC,大天朝的数据结构啊) code:

#include<iostream>
#include<cstdio>
#include<cstring>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
struct hp{
int size,top,wson,dep,fat;
}tree[100001];
int plc[100001],ls[100001],rs[100001];
int seg[400001],delta[400001];
int totw,e,n,m,ans;
struct hq{
int u,v;
}a[200001];
int point[100001],next[200001];
void add(int u,int v)
{
e++; a[e].u=u; a[e].v=v; next[e]=point[u]; point[u]=e;
}
void build_tree(int now,int last,int depth)
{
int i;
tree[now].dep=depth;
tree[now].size=1;
tree[now].wson=0;
tree[now].fat=last;
for (i=point[now];i;i=next[i])
if (a[i].v!=last)
{
build_tree(a[i].v,now,depth+1);
tree[now].size+=tree[a[i].v].size;
if (tree[tree[now].wson].size<tree[a[i].v].size)
tree[now].wson=a[i].v;
}
}
void build_seg(int now,int tp)
{
int i;
tree[now].top=tp; plc[now]=++totw;
ls[now]=totw;
if (tree[now].wson!=0)
build_seg(tree[now].wson,tp);
for (i=point[now];i;i=next[i])
if (a[i].v!=tree[now].fat&&a[i].v!=tree[now].wson)
build_seg(a[i].v,a[i].v);
rs[now]=totw;
}
void updata(int i)
{
seg[i]=seg[i<<1]+seg[i<<1|1];
}
void paint(int i,int l,int r,int a)
{
seg[i]=a*(r-l+1);
delta[i]=a;
}
void pushdown(int i,int l,int r)
{
paint(lch,delta[i]);
paint(rch,delta[i]);
delta[i]=-1;
}
void insert(int i,int l,int r,int x,int y,int a)
{
if (x<=l&&y>=r)
{
paint(i,l,r,a);
return;
}
if (delta[i]!=-1)
pushdown(i,l,r);
if (x<=mid) insert(lch,x,y,a);
if (y>mid) insert(rch,x,y,a);
updata(i);
}
void query(int i,int l,int r,int x,int y,int a)
{
if (x<=l&&y>=r)
{
if (a==1) ans=ans+seg[i];
if (a==0) ans=ans+r-l+1-seg[i];
return;
}
if (delta[i]!=-1)
pushdown(i,l,r);
if (x<=mid) query(lch,x,y,a);
if (y>mid) query(rch,x,y,a);
}
void work(int x,int y)
{
int f1=tree[x].top,f2=tree[y].top;
ans=0;
while (f1!=f2)
{
if (tree[f1].dep<tree[f2].dep) {swap(x,y); swap(f1,f2);}
query(1,1,n,plc[f1],plc[x],0);
insert(1,1,n,plc[f1],plc[x],1);
x=tree[f1].fat; f1=tree[x].top;
}
if (tree[x].dep>tree[y].dep) swap(x,y);
query(1,1,n,plc[x],plc[y],0);
insert(1,1,n,plc[x],plc[y],1);
printf("%d\n",ans);
}
void build(int i,int l,int r)
{
delta[i]=-1;
if (l==r)
{
seg[i]=0;
return;
}
build(lch); build(rch);
updata(i);
}
int main()
{
int i,x;
char s[20];
scanf("%d",&n);
for (i=1;i<=n-1;++i)
{
scanf("%d",&x);
x++;
add(x,i+1);
}
build_tree(1,0,0);
build_seg(1,1);
build(1,1,n);
scanf("%d",&m);
for (i=1;i<=m;++i)
{
scanf("%s",&s);
while (s[0]!='u'&&s[0]!='i')
scanf("%s",&s);
if (s[0]=='i')
{
scanf("%d",&x);
x++;
work(1,x);
}
if (s[0]=='u')
{
scanf("%d",&x);
x++; ans=0;
query(1,1,n,ls[x],rs[x],1);
insert(1,1,n,ls[x],rs[x],0);
printf("%d\n",ans);
}
}
}

T3。考试没想出来,交的30分还打的表,最后10分钟跑出来n=30的数据,吓尿了= =;

UPD:这题事实上就是一个状压DP,考虑每一个数加到一个集合中,相当于增加一个其质因数,而考虑每一个数n至多一个大于其n√的因子。于是我们能够仅仅考虑小质因子的情况,最后再减去同样大质因子。详见PoPoQQQ神犇的题解 code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
long long f[301][301],p[3][301][301];
int pri[9]={0,2,3,5,7,11,13,17,19};
struct hp{
int prime;
int set;
bool operator < (const hp &a) const
{return ((prime<a.prime)||(prime==a.prime&&set<a.set));}
}num[501];
long long P;
int main()
{
int i,j,k,t;
long long ans;
freopen("dinner.in","r",stdin);
freopen("dinner.out","w",stdout);
scanf("%d%I64d",&n,&P);
for (i=1;i<=n;++i)
{
num[i].set=0; t=i;
for (j=1;j<=8;++j)
if (t%pri[j]==0)
{
num[i].set=num[i].set+(1<<(j-1));
while (t%pri[j]==0)
t/=pri[j];
}
num[i].prime=t;
}
sort(num+2,num+n+1);
f[0][0]=1;
for (i=2;i<=n;++i)
{
if (i==2||num[i].prime==1||num[i].prime!=num[i-1].prime)
{
memcpy(p[1],f,sizeof(f));
memcpy(p[2],f,sizeof(f));
}
for (j=255;j>=0;--j)
for (k=255;k>=0;--k)
if ((j&k)==0)
{
if ((k&num[i].set)==0) p[1][j|num[i].set][k]=(p[1][j|num[i].set][k]+p[1][j][k])%P;
if ((j&num[i].set)==0) p[2][j][k|num[i].set]=(p[2][j][k|num[i].set]+p[2][j][k])%P;
}
if (i==n||num[i].prime==1||num[i].prime!=num[i+1].prime)
{
for (j=0;j<=255;++j)
for (k=0;k<=255;++k)
if ((j&k)==0)
{
f[j][k]=((p[1][j][k]+p[2][j][k]-f[j][k])%P+P)%P;
}
}
}
ans=0;
for (i=0;i<=255;++i)
for (j=0;j<=255;++j)
if ((i&j)==0)
ans=(ans+f[i][j])%P;
printf("%I64d\n",ans);
}

DAY2:

T1,考虑两个数的编码不存在一个是还有一个前缀的,在树上就相当于不存在两个点之间有父子关系。

而长度最短就相当于让权值与到根路径的乘积和最短。

这不就是k叉哈夫曼树么,对于不够k的能够先补零,然后同合并果子code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct hp{
long long num;
int dep;
bool operator < (const hp &a) const
{return (num>a.num)||(num==a.num&&dep>a.dep);}
};
int n,k;
priority_queue<hp> q;
int main()
{
long long a,x,ans=0;
int i,depth;
freopen("epic.in","r",stdin);
freopen("epic.out","w",stdout);
hp minn;
scanf("%d%d",&n,&k);
for (i=1;i<=n;++i)
{
scanf("%lld",&a);
q.push((hp){a,0});
}
if (k!=2)
{
while (n%(k-1)!=1)
{
n++;
q.push((hp){0,0});
}
}
while (n!=1)
{
x=0; depth=0;
for (i=1;i<=k;++i)
{
minn=q.top();
x=x+minn.num;
depth=max(depth,minn.dep);
q.pop();
}
n=n-k+1;
ans+=x;
q.push((hp){x,depth+1});
}
minn=q.top();
printf("%lld\n%d\n",ans,minn.dep);
}

T2:学后缀数组在BZOJ上就做了两道题,【AHOI 2013】差异和【JSOI 2007】字符加密。后者是裸题,而前者差点儿与此题一模一样,都能够分治的做。做法似乎被卡了常数,按点时限可能会T一到两个点。总时限的话没有问题。

code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
#define inf 2100000000LL
using namespace std;
char s[300001];
int n,maxm;
int sa[300001],rank[300001],height[300001];
int c[300001],x[300001],y[300001];
long long val[300001];
int t,ti;
long long txl,txr,tnl,tnr;
struct hq{
long long tot,maxn;
}ans[300001];
struct hp{
int sim,mini;
long long minn,maxn;
}seg[1200001];
bool cmp(int *y,int i,int j,int k)
{
int a,b,c,d;
a=y[i]; b=y[j];
c=i+k>=n?-1:y[i+k]; d=j+k>=n? -1:y[j+k];
return a==b&&c==d;
}
void build_sa()
{
int i,j,k;
for (i=0;i<maxm;++i) c[i]=0;
for (i=0;i<n;++i) c[x[i]=s[i]]++;
for (i=1;i<maxm;++i) c[i]+=c[i-1];
for (i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
for (k=1;k<=n;k<<=1)
{
int p=0;
for (i=n-k;i<n;++i) y[p++]=i;
for (i=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;
for (i=0;i<maxm;++i) c[i]=0;
for (i=0;i<n;++i) c[x[y[i]]]++;
for (i=1;i<maxm;++i) c[i]+=c[i-1];
for (i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1; x[sa[0]]=0;
for (i=1;i<n;++i)
x[sa[i]]=cmp(y,sa[i],sa[i-1],k)?p-1:p++;
if (p>=n) break;
maxm=p;
}
for (i=0;i<n;++i)
rank[sa[i]]=i;
k=0;
for (i=0;i<n;++i)
{
if (!rank[i]) continue;
if (k) k--;
j=sa[rank[i]-1];
while (s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
void updata(int i)
{
seg[i].sim=min(seg[i<<1].sim,seg[i<<1|1].sim);
if (seg[i<<1].sim<=seg[i<<1|1].sim) seg[i].mini=seg[i<<1].mini;
else seg[i].mini=seg[i<<1|1].mini;
seg[i].minn=min(seg[i<<1].minn,seg[i<<1|1].minn);
seg[i].maxn=max(seg[i<<1].maxn,seg[i<<1|1].maxn);
}
void build(int i,int l,int r)
{
if (l==r)
{
seg[i].sim=height[l];
seg[i].mini=l;
seg[i].minn=seg[i].maxn=val[l];
return;
}
build(lch); build(rch);
updata(i);
}
void query(int i,int l,int r,int x,int y,int kind)
{
if (x<=l&&y>=r)
{
if (kind==0)
if (seg[i].sim<t)
{t=seg[i].sim; ti=seg[i].mini;}
if (kind==1)
{txl=max(txl,seg[i].maxn); tnl=min(tnl,seg[i].minn);}
if (kind==2)
{txr=max(txr,seg[i].maxn); tnr=min(tnr,seg[i].minn);}
return;
}
if (x<=mid) query(lch,x,y,kind);
if (y>mid) query(rch,x,y,kind);
}
void work(int l,int r)
{
int tti;
if (l==r) return;
t=n+1; ti=-1;
query(1,0,n-1,l+1,r,0);
tti=ti;
ans[t+1].tot=ans[t+1].tot+(long long)((long long)(r-ti+1)*(long long)(ti-l));
txl=-inf; tnl=inf; query(1,0,n-1,l,ti-1,1);
txr=-inf; tnr=inf; query(1,0,n-1,ti,r,2);
ans[t+1].maxn=max(ans[t+1].maxn,max(txl*txr,tnl*tnr));
work(l,tti-1); work(tti,r);
}
int main()
{
int i;
int a;
freopen("savour.in","r",stdin);
freopen("savour.out","w",stdout);
scanf("%d",&n);
scanf("%s",&s);
while (s[0]<'a'||s[0]>'z')
scanf("%s",&s);
for (i=0;i<n;++i)
maxm=max(maxm,(int)(s[i]));
maxm++;
build_sa();
for (i=0;i<n;++i)
{
scanf("%d",&a);
val[rank[i]]=(long long)a;
ans[i+1].tot=0;
ans[i+1].maxn=-1000000000000000000LL;
}
build(1,0,n-1);
work(0,n-1);
for (i=n-1;i>=1;--i)
{ans[i].tot=ans[i].tot+ans[i+1].tot; ans[i].maxn=max(ans[i].maxn,ans[i+1].maxn);}
for (i=1;i<=n;++i)
{
if (ans[i].tot==0) ans[i].maxn=0;
printf("%lld %lld\n",ans[i].tot,ans[i].maxn);
}
}

T3并没有看懂题解,(我会说我连题目都看得迷迷糊糊的么= =)

以后再研究吧= =

NOI 2015 滞后赛解题报告的更多相关文章

  1. ZROIDay4-比赛解题报告

    ZROIDay4-比赛解题报告 扯闲话 感觉这个出题人的题做起来全都没感觉啊,今天又凉了,T1完全不知道什么意思,T2只会暴力,T3现在还不懂什么意思,真的太菜了 A 题意半天没搞懂爆零GG了,讲了一 ...

  2. ZROIDay3-比赛解题报告

    ZROIDay3-比赛解题报告 瞎扯 从今天开始考试有点不在状态,可能是因为不太适应题目的原因,T1已经接近了思想但是没有想到状态转移,T2思考方向错误,T3不会打LCT,还是太菜了 A 考场上想到要 ...

  3. 10.30 NFLS-NOIP模拟赛 解题报告

    总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没 ...

  4. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  5. 2018.10.26NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 70\) 实际得分:\(40 + 100 + 70\) 妈妈我又挂分了qwq..T1过了大样例就没管,直到临考试结束前\(10min\)才发现大样例是假 ...

  6. [ACM]2013山东省“浪潮杯”省赛 解题报告

    题目地址:http://acm.upc.edu.cn/problemset.php?page=13  2217~2226 A.Rescue The Princess 一个等边三角形告诉前2个点,求逆时 ...

  7. 2014北邮新生归来赛解题报告a-c

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...

  8. 11.1NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 50\) 实际得分:\(100 + 100 + 50\) 感觉老师找的题有点水呀. 上来看T1,woc?裸的等比数列求和?然而我不会公式呀..感觉要凉 ...

  9. 2018.10.17NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 +100\) 实际得分:\(100 + 100 + 60\) 辣鸡模拟赛.. 5min切掉T1,看了一下T2 T3,感觉T3会被艹爆因为太原了.. 淦了20 ...

随机推荐

  1. 配置maven报错 the java_home environment variable is not defined correctly ......

    the java_home environment variable is not defined correctly This environment variable is needed to r ...

  2. java缓存的使用

    缓存1,缓存的定义与作用2,缓存的使用范围(命中率高.高访问量)3,缓存策略(命中率,最大元素,清空策略);4,缓存介质(内存缓存,硬盘缓存,数据库缓存)(本地缓存(ehcache,oscache)与 ...

  3. More Effective C++ - 章节二 : 操作符(operators)

    5. 对定制的 "类型转换函数" 保持警觉 允许编译器执行隐式类型转换,害处多过好处,不要提供转换函数,除非你确定需要. class foo { foo(int a = 0, in ...

  4. LeetCode(101)Symmetric Tree

    题目 Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). Fo ...

  5. virtualbox创建虚机后配置网络上网

    一般来说常用的会配置两个网卡:(两个网卡应该在安装虚拟机之前就设置好) 1.NAT网络: 用于上外网: 2.host-only: 用于ssh连接,可以被其他人远程访问. 前提: 如图:在virtual ...

  6. 解决Can’t finish GitHub sharing process Successfully created project ‘GitHubDemo’ on GitHub

    Can't finish GitHub sharing process        Successfully created project 'KeyWordsFrameWork' on GitHu ...

  7. Go循环语句

    package main import ( "fmt" "strconv" "os" "bufio" ) //for的条 ...

  8. POJ1201:Intervals【差分约束】

    题目大意:给出N个闭区间,每个区间给出一个ci值,让你找出最小的数集Z使得每个闭区间都有不少于ci个Z中的元素,求card(Z) 思路:06年集训队论文<浅析差分约束系统>有详细的解题,设 ...

  9. 【frameset】frameset设置不能拖动

    <frameset rows='20%,*' >           <!--  row 行 col 列    分行列要为rows  cols  --> <frame s ...

  10. Heredoc和Nowdoc

    就象heredoc结构类似于双引号字符串,Nowdoc结构是类似于单引号字符串的.Nowdoc结构很象heredoc结构,但是 nowdoc不进行解析操作 . 这种结构很适合用在不需要进行转义的PHP ...