连炸两题,身败名裂。

看来不拍暴力就会die。

A题

滑动窗口或什么前缀和二分之类的就行了。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
typedef long long ll;
const int maxn=;
int n,ans1,ans2;
ll S[maxn],m;
int main() {
n=read();m=read();
rep(i,,n) S[i]=S[i-]+read();
rep(i,,n) {
int l=,r=i;
while(l<r) {
int mid=l+r>>;
if(S[i]-S[mid-]>m) l=mid+;
else r=mid;
}
if(S[i]-S[l-]==m&&!ans1) ans1=l,ans2=i;
}
printf("%d %d\n",ans1,ans2);
return ;
}

B题

好像是有奇怪的进制加法可以做。

我的做法是这样的,先计算出{1,2,--,n}变换到A的次数。

然后逐位确定乱搞。

但是要写高精度。

然后我因为构造函数写成了int炸了。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
typedef long long ll;
const int maxn=;
struct bign {
int s[maxn],len;
bign() {len=;memset(s,,sizeof(s));}
void operator = (ll b) { //嘿嘿嘿考试时写成了int
len=;
while(b) s[len++]=b%,b/=;
}
bign operator * (int b) {
bign c;c.len=len+;
int last=;
rep(i,,c.len-) {
int x=s[i]*b+last;
c.s[i]+=x%;
last=x/;
}
while(c.len>&&!c.s[c.len-]) c.len--;
return c;
}
bign operator + (bign b) {
bign c;c.len=max(len,b.len)+;
rep(i,,c.len-) {
c.s[i]+=s[i]+b.s[i];
c.s[i+]+=c.s[i]/;
c.s[i]%=;
}
while(c.len>&&!c.s[c.len-]) c.len--;
return c;
}
bool operator >= (bign b) {
if(len>b.len) return ;
if(len<b.len) return ;
dwn(i,len-,) {
if(s[i]>b.s[i]) return ;
if(s[i]<b.s[i]) return ;
}
return ;
}
bool operator > (bign b) {
if(len>b.len) return ;
if(len<b.len) return ;
dwn(i,len-,) {
if(s[i]>b.s[i]) return ;
if(s[i]<b.s[i]) return ;
}
return ;
}
void print() {
dwn(i,len-,) printf("%d",s[i]);
printf("\n",len);
}
};
int n,A[maxn],B[maxn],use[maxn];
bign m,xp[maxn];
int main() {
xp[]=;rep(i,,) xp[i]=xp[i-]*i;
n=read();ll tmp;scanf("%lld",&tmp);m=tmp;
rep(i,,n) A[i]=read();
rep(i,,n) {
int cnt=;
rep(j,i+,n) if(A[j]<A[i]) cnt++;
m=m+(xp[n-i]*cnt);
}
if(m>=xp[n]) {puts("-1");return ;}
bign cur;cur=;
rep(i,,n) {
rep(j,,n-) {
if(cur+xp[n-i]>m) {B[i]=j;break;}
cur=cur+xp[n-i];
}
}
rep(i,,n) {
rep(j,,n) if(!use[j]) {
if(B[i]==) use[j]=,printf("%d%c",j,i==n?'\n':' ');
B[i]--;
}
}
return ;
}

C题

大意是对每一行有N条带权线段,对于每个位置计算出覆盖它的线段的最大权值。

扫描线用个堆来维护一下就行了。

然后我想错了用了个单调队列,成功炸掉90分。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<queue>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
using namespace std;
typedef long long ll;
inline ll read() {
ll x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
const int maxm=;
int n,m;
ll D[maxn][maxm],A[maxn][maxm];
int L[maxn][maxm],R[maxn][maxm];
struct Line {
int l,r;ll v;
bool operator < (const Line& ths) const {return l<ths.l;}
}B[maxm];
struct HeapNode {
ll d;int u;
bool operator < (const HeapNode& ths) const {return d<ths.d;}
};
int main() {
n=read();m=read();
rep(i,,n) rep(j,,m) A[i][j]=read();
rep(i,,n) rep(j,,m) L[i][j]=read();
rep(i,,n) rep(j,,m) R[i][j]=read();
rep(i,,n) {
rep(j,,m) A[i][j]+=D[i][j],printf("%lld%c",A[i][j],j==m?'\n':' ');
rep(j,,m) B[j]=(Line){L[i][j],R[i][j],A[i][j]};
sort(B+,B+m+);
int cur=;priority_queue<HeapNode>Q; //嘿嘿嘿考试时用了一个单调队列
rep(j,,m) {
while(cur<=m&&B[cur].l<=j) Q.push((HeapNode){B[cur].v,cur}),cur++;
while(!Q.empty()) {
HeapNode x=Q.top();
if(B[x.u].r>=j) {
D[i+][j]=x.d;
break;
}
else Q.pop();
}
}
}
return ;
}

D题

对于每一个交换子树操作,左子树的所有点的答案要加上右子树的size,右子树的所有点的答案要减去左子树的size。

然后找一个支持区间增加单点查询的数据结构如线段树,BIT就行了。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
int n,clo,l[maxn],r[maxn],A[maxn],in[maxn];
int s[maxn],L[maxn],R[maxn];
int dfs(int x) {
A[x]=clo++;L[x]=clo;s[x]=;
if(l[x]) s[x]+=dfs(l[x]);
if(r[x]) s[x]+=dfs(r[x]);
R[x]=clo;
return s[x];
}
int addv[maxn*];
void pushdown(int o) {
if(addv[o]) {
int lc=o<<,rc=lc|;
addv[lc]+=addv[o];addv[rc]+=addv[o];
addv[o]=;
}
}
int pos,ql,qr,val;
void update(int o,int l,int r) {
if(ql<=l&&r<=qr) addv[o]+=val;
else {
pushdown(o);
int mid=l+r>>,lc=o<<,rc=lc|;
if(ql<=mid) update(lc,l,mid);
if(qr>mid) update(rc,mid+,r);
}
}
void query(int o,int l,int r) {
if(l==r) printf("%d\n",addv[o]);
else {
pushdown(o);
int mid=l+r>>,lc=o<<,rc=lc|;
if(pos<=mid) query(lc,l,mid);
else query(rc,mid+,r);
}
}
int main() {
n=read();
rep(i,,n) {
int p=read(),c=read(),t=read();in[c]++;
if(t) r[p]=c;
else l[p]=c;
}
rep(i,,n) if(!in[i]) dfs(i);
rep(i,,n) ql=L[i],qr=L[i],val=A[i],update(,,n);
dwn(i,read(),) {
int t=read(),x=read();
if(t==) pos=L[x],query(,,n);
else {
if(!l[x]||!r[x]) continue;
ql=L[l[x]];qr=R[l[x]];val=s[r[x]];
update(,,n);
ql=L[r[x]];qr=R[r[x]];val=-s[l[x]];
update(,,n);
swap(l[x],r[x]);
}
}
return ;
}

E题

设f[i][j]表示已经走了i步,该匹配j位置的方案数。

然后可以枚举下一位是什么:
f[i+1][to(j,0)]+=f[i][j]

f[i+1][to(j,1)]+=f[i][j]

注意如果to(j,c)=m,则要同时转移到f[i+1][m],f[i+1][0]。

然后矩阵快速幂即可。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
using namespace std;
typedef long long ll;
inline ll read() {
ll x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
const int maxn=;
const int mod=;
char s[maxn];
int m,f[maxn];
void KMP() {
f[]=f[]=;
for(int i=;s[i];i++) {
int j=f[i];
while(j&&s[i]!=s[j]) j=f[j];
f[i+]=(s[i]==s[j]?j+:);
}
}
struct Matrix {
ll A[maxn][maxn];
Matrix operator * (const Matrix& b) {
Matrix c;
rep(i,,m) rep(j,,m) {
c.A[i][j]=;
rep(k,,m) (c.A[i][j]+=A[i][k]*b.A[k][j])%=mod;
}
return c;
}
void print() {
rep(i,,m) {
rep(j,,m) printf("%lld%c",A[i][j],j==m?'\n':' ');
}
}
};
void pow(Matrix& ans,ll n) {
Matrix t;t=ans;n--;
while(n) {
if(n%) ans=ans*t;
t=t*t;n/=;
}
}
Matrix ans;
int main() {
ll n=read();scanf("%s",s);
m=strlen(s);KMP();
rep(j,,m-) rep(c,,) {
int k=j;while(k&&s[k]!=c+'') k=f[k];
if(s[k]==c+'') {
ans.A[k+][j]++;
if(k+==m) ans.A[][j]++;
}
else ans.A[][j]++;
}
pow(ans,n);
printf("%lld\n",ans.A[m][]);
return ;
}

ccc2016的更多相关文章

  1. BZOJ4563: [Haoi2016]放棋子

    Description 给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在 这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行 ...

随机推荐

  1. 基本二叉搜索树的第K小元素

    #include<stdio.h> #include<stdlib.h> typedef struct node *btlink; struct node { int data ...

  2. MySQL之扩展(触发器,存储过程等)

    视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. SELECT * FROM ( SEL ...

  3. docker的四种网络模式

    /* 1. host模式 : docker run 使用 --net=host指定 docker使用的网络实际上和宿主机一样 2. container模式: 使用 --net=container:co ...

  4. .Net Attribute特性

    1.什么是Atrribute 首先,我们肯定Attribute是一个类,下面是msdn文档对它的描述: 公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标 ...

  5. 《ASP.NET1200例》各种类型文件汇总

    aspx是页面文件 ascx是用户控件,用户控件必须嵌入到aspx中才能使用. ascx是用户控件,相当于模板 其实ascx你可以理解为Html里的一部分代码, 只是嵌到aspx里而已, 因为aspx ...

  6. 【转】 Mybatis/Ibatis,数据库操作的返回值

    该问题,我百度了下,根本没发现什么有价值的文章:还是看源代码(详见最后附录)中的注释,最有效了!insert,返回值是:新插入行的主键(primary key):需要包含<selectKey&g ...

  7. Windows下配置Tomcat服务器

    Tomcat服务器是Apache开源基金会的一个项目,tomcat不仅能作为静态文件的服务器,也可以作为JSP/Servlet的web容器,而且使用广泛,性能也不错,那么下面来配置一个基本的基于tom ...

  8. CodeForces - 404A(模拟题)

    Valera and X Time Limit: 1000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Submit ...

  9. Popular Cows(codevs 2186)

    题意: 有N(N<=10000)头牛,每头牛都想成为most poluler的牛,给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表 ...

  10. Android之Intent深入

    Android中的意图包含多种用法,本文主要包括以下内容 显式意图 隐匿意图 要求结果回传的意图 显式意图 :必须指定要激活的组件的完整包名和类名 (应用程序之间耦合在一起) 一般激活自己应用的组件的 ...