3.25省选测试
$15+100+25$,还是太菜了,结论题和数据结构还是有点问题
以后文章大概不会在洛谷更新了,洛谷机房的人会看到一些我的吐槽.,然后我被吐槽...这个博客园机房并没有人知道(毕竟全机房就我写博客)
其实我并不是很喜欢现在机房的氛围,我希望看到的是一起卷题,一起做一件喜欢的事,互相帮助,每天很积极很乐观,思想很正派,每个人都不虚伪,成绩很真实,也不怕挫折,不因为虚荣去欺骗,这样的一个团队才是我喜欢的,或许我永远不能在这个团队看到了......(好希望被一个团队收留,有没有人要我啊$QAQ$)
$T1$
考场上想到了暴力建树,贪心求期望,只能过$m=2^k$
$m=2^k$结论比较显然,我们把概率二进制分解之后,显然每个有$1$的位置占一个子树就好了
$Ans=\sum_{i}i\times 2^{-i}$
考试时候倒是知道这个式子,我没想到这个竟然在任何时候都能用...
两个结论式$:$
$f(2\times p)=2(f(p)+p)\ \ \ \ \ [p<=\frac{1}{2}]$
$f(2\times p-1)=2(f(p)+p)\ \ \ \ \ [p>\frac{1}{2}]$
首先对于奇数的情况(偶数就是在基环树上多了几个分支)
奇数可以通过这个式子回到自己,那么就可以列出方程解出来了
#include<bits/stdc++.h> #define int long long #define mod 998244353 #define MAXM 10000005 #define MAXN 1000005 using namespace std; int Inv2,Invm,sum,top,res,n; int my_2[MAXM],Ans[MAXM],sta[MAXM],a[MAXN]; bool bl[MAXM],vis[MAXM]; int my_pow(int a,int b) { int res=1; while(b) { if(b&1) { res=(res*a)%mod; } a=(a*a)%mod; b>>=1; } return res; } void Init(int Maxn) { my_2[0]=1; Inv2=my_pow(2,mod-2); for(int i=1;i<=Maxn;i++) { my_2[i]=(my_2[i-1]*Inv2)%mod; } } int Nxt(int x) { x<<=1; if(x>=sum) x-=sum; return x; } void Get(int x) { int to=Nxt(x); int v=x*Invm%mod,k=1; while(to!=x) { v+=my_2[k++]*to%mod*Invm%mod; v%=mod; to=Nxt(to); } Ans[x]=v*my_pow((1-my_2[k]+mod)%mod,mod-2)%mod; bl[x]=true; } signed main() { scanf("%lld",&n); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); sum+=a[i]; } Init(sum); Invm=my_pow(sum,mod-2); for(int i=0;i<=sum-1;i++) { if(!vis[i]) { int now=i; while(!vis[now]) { sta[++top]=now; vis[now]=true; now=Nxt(now); } if(!bl[Nxt(sta[top])]) { Get(sta[top--]); } while(top) { now=sta[top--]; Ans[now]=Inv2*Ans[Nxt(now)]+now*Invm; Ans[now]%=mod; bl[now]=true; } } } for(int i=1;i<=n;i++) { res+=Ans[a[i]]; res%=mod; } cout<<res<<"\n"; }
T2
二分图染色+补图+背包
#include<bits/stdc++.h> #define INF 2147483647 #define MAXM 1100000 #define MAXN 5005 using namespace std; int Num[3],Ans=INF,Min,n,m; int head[MAXM],nxt[MAXM],col[MAXM],to[MAXM],A[MAXM],tot,cnt; bitset<1005>Sit[1005]; struct node { int num0,num1; }val[MAXN]; void add(int u,int v) { tot++; to[tot]=v; nxt[tot]=head[u]; head[u]=tot; } void dfs(int now,int fa,int num) { col[now]=num; Num[col[now]]++; for(int i=head[now];i;i=nxt[i]) { int y=to[i]; if(y==fa) continue; if(col[now]==col[y]) { puts("-1"); exit(0); } if(col[y]==-1)dfs(y,now,(num+1)%2); } } bitset<2005>dp[2]; int main() { scanf("%d%d",&n,&m); for(int i=1,u,v;i<=m;i++) { scanf("%d%d",&u,&v); Sit[u][v]=1; Sit[v][u]=1; } for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { if(Sit[i][j]==0) add(i,j),add(j,i); } } memset(col,-1,sizeof(col)); for(int i=1;i<=n;i++) { if(col[i]==-1) { Num[0]=Num[1]=0,dfs(i,i,0),val[++cnt].num0=Num[0],val[cnt].num1=Num[1]; // cout<<Num[0]<<" "<<Num[1]<<endl; } } dp[0][0+1000]=1; //A-B的差的情况 for(int i=1;i<=cnt;i++) { int now=i%2; int pre=now^1; dp[now]=(dp[pre]>>val[i].num0<<val[i].num1)|(dp[pre]<<val[i].num0>>val[i].num1); } for(int i=0;i<=1000;i++) { if(dp[cnt%2][1000+i]||dp[cnt%2][1000-i]) { cout<<min((n+i)/2,(n-(n+i)/2)); break; } } // system("pause"); }
$T3$
暴力斜挂,只过了一个$sub$
确实不太知道最小的点怎么挂了,$/dk$
首先维护一个区间$mex$最大值,就很不太能维护的样子,主要是修改不是很好修
想到了离线处理,考虑枚举答案
假设这段区间$0-(y-1)$出现了,那么我们只需要判定$y$有没有存在即可
我们将出现$y$的位置标为$black$,没出现标为$white$,对序列建立线段树,没有被完全覆盖的区间标记为灰色,对于一组区间询问,直接查询是否全为白色即可
先考虑一下,树套树,内层维护树维护修改,外层树维护询问,大概每次修改只需要对应区间的权值线段树都加入一个数字,查询一下没出现的最小值就好了
大概上是理解了
其实就是我们对于每一个修改,把修改放在线段树上,通过维护关键点来更新答案
我们的关键点是上到下是灰变白,灰变黑节点的儿子,我们考虑这个点的答案是什么 ,就是这些黑点的没出现的最小值,其实很像曾经的一个在节点维护$pq$的思路
又透彻了一遍,大概明白了,对于每次修改直接放关键点就好了,然后答案就是这些数字所有的没出现的最小的,由于每个事没出现的,那么我们找一下最小的没出现的,然后在所有区间找个最大的就好了
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define rs ((x<<1)|1) #define MAXN 200500 #define ls (x<<1) using namespace std; inline int rd(){ int r = 0 , w = 1; char ch = getchar(); while(ch > '9' || ch < '0') {if(ch == '-') w = -1; ch = getchar();} while(ch >='0' && ch <='9') {r = r * 10 + ch -'0'; ch = getchar();} return r * w; } int q,n=200010; struct range { int l,r; range(){} range(int _l,int _r=0){l=_l;r=_r;} friend bool operator < (range a,range b) { return a.l==b.l?a.r<b.r:a.l<b.l; } }; struct node { int l,r,ans; set<int>s; }tr[MAXN<<2]; map<pair<int,int>,bool>Black,Gray; set<range>rg[MAXN]; void Gaib(int x,int k,bool opt) { if(Black.count(make_pair(x,k))||Gray.count(make_pair(x,k)))return; if(tr[x].s.find(k)==tr[x].s.end()&&opt) tr[x].s.insert(k); else if(opt==0) tr[x].s.erase(k); if(!tr[x].s.empty()) { if(tr[x].l==tr[x].r) tr[x].ans=INF; else tr[x].ans=max(tr[ls].ans,tr[rs].ans); tr[x].ans=min(tr[x].ans,*(tr[x].s.begin())); } else if(tr[x].l==tr[x].r) tr[x].ans=INF; else tr[x].ans=max(tr[ls].ans,tr[rs].ans); } void push_up(int x,int k) { bool opt=Gray.count(make_pair(x,k)); if(tr[x].l==tr[x].r) tr[x].ans=INF; else { Gaib(ls,k,opt); Gaib(rs,k,opt); tr[x].ans=max(tr[ls].ans,tr[rs].ans); } if(!tr[x].s.empty()) tr[x].ans=min(tr[x].ans,*(tr[x].s.begin())); } void color_black(int x , int k) { tr[x].s.erase(k); if(!Black.count(make_pair(x,k))) Black.insert(make_pair(make_pair(x,k),1)); } void update(int x,int l,int r,int k) { if(l<=tr[x].l&&tr[x].r<=r) { color_black(x,k); push_up(x,k); return; } if(!Gray.count(make_pair(x,k))) Gray.insert(make_pair(make_pair(x,k),1)); tr[x].s.erase(k); int mid=tr[x].l+tr[x].r>>1; if(l<=mid) update(ls,l,r,k); if(r>mid) update(rs,l,r,k); push_up(x,k); } int query(int x,int l,int r) { if(l<=tr[x].l&&tr[x].r<=r) return tr[x].ans; int mid = tr[x].l+tr[x].r>>1; int res=0; if(l<=mid) res=max(res,query(x<<1,l,r)); if(r>mid) res=max(res,query(rs,l,r)); if(res==0) res=INF; if(!tr[x].s.empty()) res=min(res,*(tr[x].s.begin())); return res; } void Insert(set<range>&s,int l,int r,int k) { auto pre=s.lower_bound(range(l)); if(pre!=s.begin()) { pre--; if(pre->r>r) return; l=max(l,pre->r+1); } if(l>r) return; int last=l; for(auto its=s.lower_bound(range(l));its!=s.end();) { if(its->l>r) break; if(last<=its->l-1) update(1,last,its->l-1,k); if(its->r>=r) { if(l<=its->l-1) s.insert(range(l,its->l-1)); return; } last=its->r+1; s.erase(its++); } if(last<=r) update(1,last,r,k); s.insert(range(l,r)); } void build(int x ,int l,int r){ tr[x].ans=INF; tr[x].l=l; tr[x].r=r; if(l==r) return; int mid=l+r>>1; build(ls,l,mid); build(rs,mid+1,r); } int S; signed main() { freopen("starlight.in","r",stdin); freopen("starlight.out","w",stdout); build(1,1,n); for(int i=1;i<=n;i++) tr[1].s.insert(i); tr[1].ans=1; q=rd(); while(q--) { int opt=rd(); if(opt==1) { int k=rd(),l=rd(),r=rd(); k=k^S,l=l^S,r=r^S; Insert(rg[k+1],l+1,r+1,k+1); } else { int l=rd(),r=rd(); l=l^S,r=r^S; int ans=query(1,l+1,r+1)-1; S+=ans; cout<<ans<<"\n"; } } return 0; }
毕竟我是我,我看不惯的人,无法改变就不必在意,终成路人而已,无须为此耗时,一笑而过即可