您的位置:首页 > 其它

FR #13题解

2017-02-20 14:28 106 查看
A.

  有点像学军中学的一道NOIP模拟赛的题。因为插入的顺序唯一,然后就完了。。。

具体操作是在线段树上二分,然后区间赋值1等等。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxv 100500
#define maxe 200500
using namespace std;
int n,q,x,y,g[maxv],nume=1,w[maxv],fw[maxv],dis[maxv],cnt=0,tot=0,anc[maxv][20],val[maxv];
int ls[maxv<<2],rs[maxv<<2],lazy[maxv<<2],sum[maxv<<2],root,tr_root;
int t=0;
struct status
{
int id,val;
status (int id,int val):id(id),val(val) {}
status () {}
};
vector <status> v[maxv];
struct edge
{
int v,nxt;
}e[maxe];
bool cmp(status x,status y) {return x.val<y.val;}
void addedge(int u,int v)
{
e[++nume].v=v;e[nume].nxt=g[u];
g[u]=nume;
}
void dfs1(int x)
{
val[x]=x;
for (int i=g[x];i;i=e[i].nxt)
{
int v=e[i].v;
if (v!=anc[x][0])
{
anc[v][0]=x;dis[v]=dis[x]+1;
dfs1(v);
val[x]=min(val[x],val[v]);
}
}
}
void dfs2(int x)
{
for (int i=g[x];i;i=e[i].nxt)
{
int vs=e[i].v;
if (vs==anc[x][0]) continue;
v[x].push_back(status(vs,val[vs]));
}
sort(v[x].begin(),v[x].end(),cmp);
for (int i=0;i<v[x].size();i++) dfs2(v[x][i].id);
w[x]=++cnt;fw[cnt]=x;
}
void build(int &now,int left,int right)
{
now=++tot;sum[now]=lazy[now]=0;
if (left==right) return;
int mid=(left+right)>>1;
build(ls[now],left,mid);
build(rs[now],mid+1,right);
}
void pushdown(int now,int left,int right)
{
if (!lazy[now]) return;
lazy[ls[now]]=lazy[rs[now]]=1;lazy[now]=0;
int mid=(left+right)>>1;
sum[ls[now]]=mid-left+1;sum[rs[now]]=right-mid;
}
int modify1(int now,int left,int right,int k)
{
pushdown(now,left,right);
if (left==right) {sum[now]=1;return fw[left];}
int mid=(left+right)>>1,r=(mid-left+1-sum[ls[now]]),ret;
if (k>r) sum[ls[now]]=mid-left+1,lazy[ls[now]]=1;
if (k>r) ret=modify1(rs[now],mid+1,right,k-r);
else ret=modify1(ls[now],left,mid,k);
sum[now]=sum[ls[now]]+sum[rs[now]];
return ret;
}
int ask(int now,int left,int right,int pos)
{
if (!pos) return 0;
pushdown(now,left,right);
if (left==right) return sum[now];
int mid=(left+right)>>1;
if (pos<=mid) return ask(ls[now],left,mid,pos);
else return ask(rs[now],mid+1,right,pos);
}
void modify2(int now,int left,int right,int pos)
{
pushdown(now,left,right);
if (left==right) {sum[now]=0;return;}
int mid=(left+right)>>1;
if (pos<=mid) modify2(ls[now],left,mid,pos);
else modify2(rs[now],mid+1,right,pos);
sum[now]=sum[ls[now]]+sum[rs[now]];
}
void work2()
{
int reg=y;
for (int e=19;e>=0;e--)
{
int ret=ask(root,1,n,w[anc[y][e]]);
if (ret) y=anc[y][e];
}
modify2(root,1,n,w[y]);
printf("%d\n",dis[reg]-dis[y]);
}
int main()
{
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
if (!x) tr_root=i;
else {addedge(x,i);addedge(i,x);}
}
dfs1(tr_root);dfs2(tr_root);
for (int e=1;e<=19;e++)
for (int i=1;i<=n;i++)
anc[i][e]=anc[anc[i][e-1]][e-1];
build(root,1,n);
for (int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
if (x==1) printf("%d\n",modify1(root,1,n,y));
else work2();
}
return 0;
}


B.

  本来以为要用什么奇怪的自动机等等等等,然后。。。。

设这个数位置是n。奇数长度?a
!=a[n-2]。否则?a
!=a[n-1]。

然后数位dp一波就完了。。。

注意判0。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long a,b,dp[20][10][10],ret=0,bit[20];
void getbit(long long x)
{
ret=0;
while (x)
{
bit[++ret]=x%10;
x/=10;
}
}
long long dfs(long long now,long long pre2,long long pre1,bool flag)
{
if (!now) return 1;
if ((!flag) && (pre2!=-1) && (pre1!=-1) && (dp[now][pre2][pre1])) return dp[now][pre2][pre1];
long long ret=0,up=flag?bit[now]:9;
for (long long i=0;i<=up;i++)
{
if ((i!=pre2) && (i!=pre1))
ret+=dfs(now-1,pre1,i,flag && (i==bit[now]));
}
if ((!flag) && (pre2!=-1) && (pre1!=-1)) dp[now][pre1][pre2]=ret;
return ret;
}
long long ask(long long x)
{
if (x==-1) return 0;
getbit(x);long long ans=0;
for (long long i=1;i<=ret-1;i++)
for (long long j=1;j<=9;j++)
ans+=dfs(i-1,-1,j,0);
for (long long i=1;i<=bit[ret]-1;i++)
ans+=dfs(ret-1,-1,i,0);
ans+=dfs(ret-1,-1,bit[ret],1);
return ans;
}
int main()
{
scanf("%lld%lld",&a,&b);
if (!a) {a++;printf("%lld\n",ask(b)-ask(a-1)+1);}
else printf("%lld\n",ask(b)-ask(a-1));
return 0;
}


C.

  m>n?肯定多解。。。

m<n?废话。。。

m=n?环套树。。。然后直接按环上解方程就行了。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 100500
#define maxe 1000050
using namespace std;
int n,m,x,y,c[maxv],g[maxv],nume=1,val[maxe],d[maxv];
int top=0,flag2,flag3;
bool vis[maxv],rol[maxv],flag1,flag4;
struct edge
{
int v,nxt;
}e[maxe];
struct status
{
int id,id1,id2,val;
status (int id,int id1,int id2,int val):id(id),id1(id1),id2(id2),val(val) {}
status () {}
}s[maxv];
bool cmp(status x,status y) {return x.id<y.id;}
void addedge(int u,int v)
{
e[++nume].v=v;e[nume].nxt=g[u];
g[u]=nume;
}
void dfs1(int x,int fath,int fath_e)
{
int ret=0;
for (int i=g[x];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==fath) continue;
dfs1(v,x,i);ret-=val[i>>1];
}
val[fath_e>>1]=c[x]+ret;
}
void dfs2(int x,int fath_e)
{
vis[x]=true;
for (int i=g[x];i;i=e[i].nxt)
{
int v=e[i].v;
if ((vis[v]) && (i!=(fath_e^1)))
{
s[++top]=status(x,i>>1,fath_e>>1,c[x]);
flag1=1;flag2=v;flag3=i;rol[x]=true;
return;
}
if (vis[v]) continue;
dfs2(v,i);
if (flag1)
{
if (flag4) return;
rol[x]=true;
if (x!=flag2) s[++top]=status(x,i>>1,fath_e>>1,c[x]);
else {s[++top]=status(x,i>>1,flag3>>1,c[x]);flag4=1;}
return;
}
}
return;
}
void work1()
{
dfs1(1,1,0);
for (int i=1;i<=m;i++) printf("%d\n",val[i]<<1);
return;
}
void work2()
{
for (int i=1;i<=n;i++)
if (d[i]==1)
{dfs2(i,0);break;}
if (!(top&1)) {printf("0\n");return;}
for (int i=1;i<=n;i++)
{
if (!rol[i]) continue;
for (int j=g[i];j;j=e[j].nxt)
{
int v=e[j].v;
if (rol[v]) continue;
dfs1(v,i,j);c[i]-=val[j>>1];
}
}
int ret=0;
for (int i=1;i<=top-1;i++)
{
if (i&1) ret+=c[s[i].id];
else ret-=c[s[i].id];
}
val[s[1].id1]=(ret+c[s[top].id])/2;
for (int i=1;i<=top-1;i++)
val[s[i].id2]=c[s[i].id]-val[s[i].id1];
for (int i=1;i<=m;i++) printf("%d\n",val[i]<<1);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&c[i]);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);addedge(y,x);
d[x]++;d[y]++;
}
if (m>n) printf("0\n");
else if (m<n) work1();
else work2();
return 0;
}


怎么说呢?。。。三道题都是,只要点出了它的核心都很简单。那么重点就是那一点点思维。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: