您的位置:首页 > 其它

6.11 考试修改+总结

2016-06-11 19:24 351 查看
第三题至今没敢写,感觉好恐怖QAQ

今天考得好糟糕

第一题只写了10分的暴力+(k=1)20分的网络流

后来题解告诉我k>1的时候可以分治到k=1,每层分治解决方法是同k=1的

考试的时候没有注意到2^k这个比较神奇的可以分治的性质

而且自己考场上丝薄了,没有发现因为是二分图可以直接跑欧拉回路的性质,而是裸套网络流模型

第二题其实已经接近想出了题解

自己考试的时候成功证明了暴力的复杂度是线性的

但是没有想到如何寻找0-1对,然后就只能暴力用Splay维护1所在的位置了

默默祈祷数据不要太卡我的做法,结果最后只比裸暴力分多10分,只是悲桑

考后跟zcg交流一下发现维护一下hash值之后每次二分就可以找到0-1对了(考场上在想什么系列

但是这样会T或者WA(因为貌似卡自然溢出?瞎改几个base就可以了

还有一种做法是在线段树上直接劈开区间,然后如果哈希值相等的区间就不递归,否则递归下去改

时间复杂度略微有些玄学,但是跑的比hash+二分快

自己写的貌似会T一个点,不过懒得玩常数优化了

第三题貌似是弱化版的火龙果

不过LCT要维护一些奇怪的东西,考试的时候没有想出来怎么维护

后来看题解发现维护的方法类似疯狂的重心,LCT维护子树和

每次暴力删最大边看看是否可以不丢失解

但是感觉要码这样一坨东西好鬼畜啊

被莫名卡了常数,丢了20分的暴力分QAQ

最后貌似交到OJ上rank2?

%%%zcg

第一题代码:

写欧拉回路的时候写的比较鬼畜,但也只能这样写来保证O(m)的性质了(YY了好久,感谢jkxing

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<set>
using namespace std;

const int maxn=400010;
int n,m,k,T;
int deg[maxn];
struct Edge{
int u,v,id;
}c[maxn],Q1[maxn],Q2[maxn];
int Ans[maxn];
int h[maxn],cnt=0;
bool vis[maxn];
int check[maxn],tim;
int st[maxn],top=0;
struct edge{
int to,next,w;
}G[maxn];

void add(int x,int y,int z=0){
++cnt;G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt;
vis[cnt]=false;
}
void read(int &num){
num=0;char ch=getchar();
while(ch<'!')ch=getchar();
while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
}
void Get_euler(int u,int f){
check[u]=tim;
for(int i=h[u];i;i=h[u]){
if(vis[i]){h[u]=G[i].next;continue;}
int v=G[i].to;
vis[i]=vis[i^1]=true;
G[i].w=G[i^1].w=f;
h[u]=G[i].next;
Get_euler(v,f^1);
}return;
}
void Solve(int L,int R,int k){
if(!k)return;
cnt=1;tim++;top=0;
for(int i=L;i<=R;++i){
int u=c[i].u,v=c[i].v;
add(u,v);add(v,u);
if(check[u]!=tim)check[u]=tim,st[++top]=u;
if(check[v]!=tim)check[v]=tim,st[++top]=v;
}tim++;
for(int i=1;i<=top;++i){
if(check[st[i]]!=tim)Get_euler(st[i],0);
}
int l1=0,l2=0;
for(int i=L;i<=R;++i){
int now=(i-L+1)<<1;
int u=c[i].id;
h[c[i].u]=h[c[i].v]=0;
Ans[u]=(Ans[u]<<1)|G[now].w;
if(G[now].w)Q2[++l2]=c[i];
else Q1[++l1]=c[i];
}
for(int i=1;i<=l1;++i)c[L+i-1]=Q1[i];
for(int i=1;i<=l2;++i)c[L+l1+i-1]=Q2[i];
Solve(L,L+l1-1,k-1);Solve(L+l1,R,k-1);
}

int main(){
int __size__=128<<20;
char *__p__=(char*)malloc(__size__)+__size__;
__asm__("movl %0, %%esp\n"::"r"(__p__));
while(scanf("%d%d",&n,&m)==2){
memset(deg,0,sizeof(deg));
for(int i=1;i<=m;++i){
read(c[i].u);read(c[i].v);
c[i].id=i;
deg[c[i].u]++;deg[c[i].v]++;
}
for(k=1;k;++k){
int mk=(1<<k);
bool flag=false;
for(int i=1;i<=n;++i)if(deg[i]%mk!=0||!deg[i]){flag=true;break;}
if(flag)break;
}k--;
if(!k)printf("-1\n");
else{
memset(Ans,0,sizeof(Ans));
Solve(1,m,k);
printf("%d\n",k);
for(int i=1;i<=m;++i)printf("%d ",Ans[i]+1);
printf("\n");
}
}return 0;
}


第二题代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int maxn=1000010;
const int base=13331;
int n,m,type,L,R,len,p,x,y;
char s[maxn];
int sum[maxn<<2];
LL xp[maxn];
LL h[maxn<<2];

void read(int &num){
num=0;char ch=getchar();
while(ch<'!')ch=getchar();
while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
}
void build(int o,int L,int R){
if(L==R){
h[o]=s[L];
sum[o]=h[o]-'0';
return;
}
int mid=(L+R)>>1;
int l=(o<<1),r=(l|1);
build(l,L,mid);build(r,mid+1,R);
h[o]=h[l]*xp[R-mid]+h[r];
sum[o]=sum[l]+sum[r];
}
void UPD(int o,int L,int R){
if(L==R){
h[o]^=1;
sum[o]^=1;
return;
}
int mid=(L+R)>>1;
int l=(o<<1),r=(l|1);
if(p<=mid)UPD(l,L,mid);
else UPD(r,mid+1,R);
h[o]=h[l]*xp[R-mid]+h[r];
sum[o]=sum[l]+sum[r];
}
LL ask(int o,int L,int R){
if(L>=x&&R<=y)return h[o];
int mid=(L+R)>>1;
if(y<=mid)return ask(o<<1,L,mid);
else if(x>mid)return ask(o<<1|1,mid+1,R);
else{
LL A=ask(o<<1,L,mid);
LL B=ask(o<<1|1,mid+1,R);
return A*xp[min(y,R)-mid]+B;
}
}
int ask_S(int o,int L,int R){
if(L>=x&&R<=y)return sum[o];
int mid=(L+R)>>1;
if(y<=mid)return ask_S(o<<1,L,mid);
else if(x>mid)return ask_S(o<<1|1,mid+1,R);
else return ask_S(o<<1,L,mid)+ask_S(o<<1|1,mid+1,R);
}

int main(){
freopen("and.in","r",stdin);
freopen("and.out","w",stdout);
read(n);read(m);
scanf("%s",s+1);
xp[0]=1;
for(int i=1;i<=n;++i)xp[i]=xp[i-1]*base;
build(1,1,n);
while(m--){
read(type);
if(type==1){
read(L);read(R);read(len);
int l=1,r=len;
while(true){
while(l<r){
int mid=(l+r)>>1;
x=L;y=L+mid-1;
LL A=ask(1,1,n);
x=R;y=R+mid-1;
LL B=ask(1,1,n);
if(A==B)l=mid+1;
else r=mid;
}
x=L+r-1;y=R+r-1;
int A=s[x]-'0',B=s[y]-'0';
if(A==B)break;
if(A==1)s[x]='0',p=x,UPD(1,1,n);
else s[y]='0',p=y,UPD(1,1,n);
l=r;r=len;
}
}else if(type==2){
read(L);p=L;
if(s[L]=='1')s[L]='0';
else s[L]='1';
UPD(1,1,n);
}else{
read(L);read(R);read(len);
x=L;y=R;
int now=ask_S(1,1,n);
if(len==1)printf("%d\n",now);
else printf("%d\n",R-L+1-now);
}
}return 0;
}


第三题看看zcg他们能不能搞出来吧

感觉自己要写的话一个晚上药丸啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: