2.8模拟总结
前言
80pts
30+30+20
rnk10
三個暴力分…
T2拿虛樹玩了半天結果假了qwq
乍一看似乎都挺可做的。
但是一道都做不出來
(覺得寫考場過程有點流水賬,不寫了,一些想說的寫在對應題目里吧)
題目解析
T1 三角查找(triangle)
乍一看巨可做的題,但想了很久也沒做出來…
枚舉線段,在距離上二分找點的做法也想到過,但是當時就卡在如何維護點關于不同線段的距離始終有序上。
題解的做法挺巧妙的,兩個點關于某條線段的距離的偏序關系是由它們連線和當前線段斜率相對大小關系決定的,所以把線段極角排序,一開始把點按照第一個線段的距離sort一遍,之后枚舉到當前線段就把線段兩端點swap一下即可。
說實話,這個玄學做法考場即使我觀察到斜率的性質可能也不太敢寫,太詭異了。
但確實是對的。
T2 連通的圖(connected)
這次考試就砸這題上了。
建個生成樹再找基環(huán)顯而易見,然后我猜了個結論,在n=2的時候都是對的(所以我就得了30分),我就以為可以推廣了。
為什么不試試n=3啊!!
然后為這個結論服務我就開始興致勃勃的建虛樹,然后寫一些類似 kkk^kkk 的暴搜,似乎能過不少分的。
但是最后事實是k=8都會T,因為我那個虛樹的結點數是 O(k)O(k)O(k),掛個四倍常數左右
…
所以我只掛了20分!
正解的關鍵是一個結論:
令第 iii 條非樹邊的權值為 2i2^i2i,樹邊權值為覆蓋其的非樹邊的異或和,則圖不連通的充要條件是斷邊集合的一個子集權值異或和為0。
這個結論似乎見到過,但是考試的時候沒有想到…
有了這個結論,寫個暴搜用線性基判一下合法就行了。
必須在搜索過程中判到非法直接返回,不然會T(別問我為什么知道)
復雜度 O(玄學)O(玄學)O(玄學)
T3 奇妙的樹(graph)
這個題的感覺挺難的,主要感覺就是方向太多了,難以找到有用的那一個。
題目的性質其實就是按照bfs序編號。
設 gi=max?j,faj<ig_i=\max j,fa_j<igi?=maxj,faj?<i,那么對于一次詢問 (l,r)(l,r)(l,r),那么所有的貢獻答案的點對有且僅有 [l,min?(r,gl)][l,\min(r,g_l)][l,min(r,gl?)] 的每個點各自的子樹內的所有點對,那么也就是編號屬于 [l,r][l,r][l,r] 的結點在子樹內權值和的平方。
如何快速統(tǒng)計這個東西?
考慮分塊,預處理時每經過 n\sqrt nn? 個結點就統(tǒng)計一遍子樹權值平方和,然后每次詢問的時候找到對應所在塊,利用預處理的前綴和快速算出答案,再把 O(n)O(\sqrt n)O(n?) 的散點暴力維護進去。
暴力維護需要一個 k 級祖先,講解說樹剖常數小都能過,我長剖 O(1)O(1)O(1) 都過不去,服了。
代碼
T1
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) #define ok debug("OK\n") inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } const int N=2e3+100; const int M=2e5+100; const double inf=1e18; const int mod=998244353;int n; ll m; struct pt{ll x,y; }p[N]; inline pt operator - (const pt &a,const pt &b){return (pt){a.x-b.x,a.y-b.y}; } inline ll operator ^ (const pt &a,const pt &b){return a.x*b.y-b.x*a.y; } struct line{int a,b;double k;bool operator < (const line oth){return k<oth.k;} }l[N*N];int tot; int x[N],A,B; inline ll calc(int x){return (p[B]-p[A])^(p[x]-p[A]); } bool cmp(int x,int y){return calc(x)<calc(y); } int find(ll val){int st=1,ed=n;while(st<ed){int mid=(st+ed)>>1;ll res=calc(x[mid]);if(res>=val) ed=mid;else st=mid+1;}return x[st]; } int pl[N];signed main(){freopen("triangle.in","r",stdin);freopen("triangle.out","w",stdout);n=read();m=read();m<<=1;for(int i=1;i<=n;i++){p[i].x=read();p[i].y=read();}for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){l[++tot]=(line){i,j,p[i].x==p[j].x?inf:1.0*(p[j].y-p[i].y)/(p[j].x-p[i].x)};}}sort(l+1,l+1+tot);A=l[1].a;B=l[1].b;for(int i=1;i<=n;i++) x[i]=i;sort(x+1,x+1+n,cmp);for(int i=1;i<=n;i++) pl[x[i]]=i;for(int i=1;i<=tot;i++){A=l[i].a;B=l[i].b;//printf("\n(%d %d) mid=%d\n",A,B,pl[A]);//for(int j=1;j<=n;j++) printf("%d ",x[j]);//puts("");int st=1,ed=pl[A],o(0);while(st<ed){int mid=(st+ed+1)>>1;// printf(" (%d %d) mid=%d calc=%lld\n",st,ed,mid,abs(calc(x[mid])));if(abs(calc(x[mid]))>=m) st=mid;else ed=mid-1;}o=x[st];//printf("o=%d\n",o);if(abs(calc(o))==m){puts("Yes");printf("%lld %lld\n",p[o].x,p[o].y);printf("%lld %lld\n",p[A].x,p[A].y);printf("%lld %lld\n",p[B].x,p[B].y);return 0;}st=pl[A],ed=n;while(st<ed){int mid=(st+ed)>>1;if(abs(calc(x[mid]))>=mid) ed=mid;else st=mid+1;}o=x[st];//printf(" o=%d\n",o);if(abs(calc(o))==m){puts("Yes");printf("%lld %lld\n",p[o].x,p[o].y);printf("%lld %lld\n",p[A].x,p[A].y);printf("%lld %lld\n",p[B].x,p[B].y);return 0;}swap(x[pl[A]],x[pl[B]]);swap(pl[A],pl[B]);}puts("No");return 0; } /* 5 2 2 4 1 5 1 2 2 3 3 4 3 5 */T2
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) #define ok debug("OK\n") inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } const int N=2e5+100; const int M=2e5+100; const int inf=1e9; const int mod=998244353;int n,m; struct node{int to,nxt; }p[N<<1]; int fi[N],cnt; bool tag[N<<1]; inline void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt; } int u[25],v[25],num; int pl[N][20],dep[N],dfn[N],tim; void dfs1(int x,int f){dep[x]=dep[f]+1;pl[x][0]=f;for(int k=1;pl[x][k-1];++k) pl[x][k]=pl[pl[x][k-1]][k-1];dfn[x]=++tim;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;if(dep[to]){tag[i]=tag[i^1]=1;if(dep[to]<dep[x]){++num;u[num]=x;v[num]=to;}continue;}dfs1(to,x);}return; } int val[N]; void dfs2(int x,int f){for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(tag[i]||to==f) continue;dfs2(to,x);val[x]^=val[to];}return; } int bac[N],w[N],tot;ll ans(0);int b[20],x[100]; int pos,ori; bool ins(int now){for(int k=m-1;k>=0;k--){if(!(now&(1<<k))) continue;if(!b[k]){pos=k;ori=b[k];b[k]=now;return true;}now^=b[k];}return false; }void solve(int k,int num,ll cur){if(k>tot){ans=(ans+cur)%mod;return;}solve(k+1,num,cur);if(ins(w[k])){int p=pos,o=ori;solve(k+1,num+1,cur*bac[w[k]]%mod);b[p]=o;} }signed main(){freopen("connected.in","r",stdin);freopen("connected.out","w",stdout);memset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<=n+m-1;i++){int x=read(),y=read();addline(x,y);addline(y,x);}dfs1(1,0);for(int i=1;i<=m;i++){//printf("(%d %d)\n",u[i],v[i]);val[u[i]]^=(1<<(i-1));val[v[i]]^=(1<<(i-1));}dfs2(1,0);for(int i=2;i<=n;i++){//printf("i=%d val=%d\n",i,val[i]);if(bac[val[i]]==0) w[++tot]=val[i];bac[val[i]]++;}for(int i=1;i<=m;i++){if(bac[1<<(i-1)]==0) w[++tot]=1<<(i-1);bac[1<<(i-1)]++;}//for(int i=1;i<=tot;i++) printf("w=%d bac=%d\n",w[i],bac[w[i]]);solve(1,0,1);printf("%lld\n",ans);return 0; } /* 5 2 2 4 1 5 1 2 2 3 3 4 3 5 */T3
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) #define ok debug("OK\n") inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } const int N=5e3+100; const int M=2e5+100; const int inf=1e9; const int mod=998244353;int n,m; struct node{int to,nxt; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt; } ll s[N][N],val[N]; void dfs(int x){s[x][x]=val[x];for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;dfs(to);for(int j=1;j<=n;j++) s[x][j]=(s[x][j]+s[to][j])%mod;} } int l,r; ll solve(int x){ll ans(0);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;ans=(ans+solve(to))%mod;}if(l<=x&&x<=r){ll now=val[x];ans=(ans+now*now)%mod;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;ll add=(s[to][r]-s[to][l-1]+mod)%mod;ans=(ans+2*now*add)%mod;now=(now+add)%mod;}}return ans; }signed main(){freopen("slight.in","r",stdin);freopen("slight.out","w",stdout);memset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<=n;i++) val[i]=read();for(int i=2;i<=n;i++) addline(read(),i);dfs(1);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++) s[i][j]=(s[i][j]+s[i][j-1])%mod;}int lst(0);for(int i=1;i<=m;i++){l=read()^lst,r=read()^lst;printf("%d\n",lst=solve(1));}return 0; } /* 5 2 2 4 1 5 1 2 2 3 3 4 3 5 */總結
- 上一篇: 模板:广义二项式反演/广义容斥(组合数学
- 下一篇: 2.10模拟总结