报同步赛的时候出了些意外。于是仅仅能做一做“滞后赛”了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. luogu P1519 穿越栅栏 Overfencing

    题目描述 描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫.幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口.更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意 ...

  2. 关于JVM内存模型,GC策略以及类加载器的思考

    JVM内存模型 Sun在2006年将Oracle JDK开源最终形成了Open JDK项目,两者在绝大部分的代码上都保持一致.JVM的内存模型是围绕着原子性(操作有且仅有一个结果).可见性(racin ...

  3. SQL语句新建数据库

    CREATE DATABASE 语句. CREATE DATABASE Epiphany ON ( NAME = Epiphany, FILENAME = 'E:\SQL SERVER 2008\Ep ...

  4. LeetCode(18)4Sum

    题目 Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = ...

  5. Android开发——GPS定位

    1.LocationManager LocationManager系统服务是位置服务的核心组件,它提供了一系列方法来处理与位置相关的问题. 与LocationManager相关的两个知识点: 1.1 ...

  6. python协程有多厉害?

    爬一个××网站上的东西,测算了一下协程的速度提升到底有多大,网站链接就不放了... import requests from bs4 import BeautifulSoup as sb import ...

  7. Leetcode 315.计算右侧小于当前元素的个数

    计算右侧小于当前元素的个数 给定一个整数数组 nums,按要求返回一个新数组 counts.数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元 ...

  8. 【ITOO 2】.NET 动态建库建表:使用SQL字符串拼接方式

    导读:在最近接手的项目(高效云平台)中,有一个需求是要当企业用户注册时,给其动态的新建一个库和表.刚开始接手的时候,是一点头绪都没有,然后查了一些资料,也问了问上一版本的师哥师姐,终于有了点头绪.目前 ...

  9. css中background-image背景图片路径设置

    web项目中经常会用到background-image:url(),很多小伙伴不知道该怎么写需要的图片路径. 在此之前先要知道几个重要的东东: /  项目根目录         这个不用多说,就是程序 ...

  10. 【dp】D. Caesar's Legions

    https://www.bnuoj.com/v3/contest_show.php?cid=9146#problem/D [题意]给定n1个A,n2个B,排成一排,要求A最多能连续k1个紧挨着,B最多 ...