连炸两题,身败名裂。

看来不拍暴力就会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. Linux Apache和Nginx的比较

    1.nginx相对于apache的优点: 轻量级,同样起web 服务,比apache占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx ...

  2. frameset框架下,刷新整个页面

    <a href="index.jsp" target="_parent">  index.jsp主frameset页面

  3. Spring配置JNDI的解决方案

    我的配置环境是:Spring + Tomcat + MySql 说明: 1. $TOMCAT_HOME代表Tomcat的安装目录. 第一步:在Tomcat的$TOMCAT_HOME/conf/cont ...

  4. [Android Pro] ant 编译android工程

    参考文章: http://blog.csdn.net/xyz_lmn/article/details/7268582?reload http://hubingforever.blog.163.com/ ...

  5. git merge和个git rebase的区别

    http://stackoverflow.com/questions/16666089/whats-the-difference-between-git-merge-and-git-rebase/16 ...

  6. sublime text3侧边栏主题不生效问题解决

    sublime text3主题插件: Seti_UI 插件安装: 在线安装:需要FQ window: ctrl+shift+p 找install package:之后搜索 Seti_UI 安装完成后需 ...

  7. InnoDB引擎的索引和存储结构

    在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的.而MySql数据库提供了多种存储引擎.用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据 ...

  8. js打印html中的内容

    js打印方法 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...

  9. php动态安装mongo扩展

    首先下载mongo扩展包  http://pecl.php.net/package/mongo 开始安装把 wget http://pecl.php.net/get/mongo-1.5.8.tgz t ...

  10. hdu 1242:Rescue(BFS广搜 + 优先队列)

    Rescue Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...