1.给出N*M的循环平面上的k对点,每对点可以按四个方向的某个方向连成矩形,问交的最大值。
显然可以将每一维分开考虑。对于一维问题,数轴上的某一个点能作为交的条件是惟一的,将这些条件哈希起来统计一下即可。
O(klogk)
1 #include<bits/stdc++.h> 2 #define p 13131 3 using namespace std; 4 typedef long long int ll; 5 typedef unsigned long long ull; 6 const int maxn=5E5+5; 7 int n; 8 int X,Y; 9 ull Hash[maxn]; 10 inline int read() 11 { 12 char ch=getchar(); 13 while(!isdigit(ch))ch=getchar(); 14 int s=ch-'0';ch=getchar(); 15 while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} 16 return s; 17 } 18 struct line 19 { 20 int l,r; 21 }a[maxn],b[maxn]; 22 struct pt 23 { 24 int x; 25 int num,type; 26 bool operator<(const pt&A)const 27 { 28 return x==A.x?type<A.type:x<A.x; 29 } 30 }P[maxn*4]; 31 inline void init() 32 { 33 Hash[0]=1; 34 for(int i=1;i<=500000;++i) 35 Hash[i]=Hash[i-1]*p; 36 } 37 inline ll solve(line*A,int len) 38 { 39 map<ull,int>bucket; 40 ull now=0; 41 int tot=0; 42 for(int i=1;i<=n;++i) 43 { 44 P[++tot]=(pt){A[i].l,i,1}; 45 P[++tot]=(pt){A[i].l,0,0}; 46 P[++tot]=(pt){A[i].r,i,2}; 47 P[++tot]=(pt){A[i].r,0,0}; 48 } 49 P[++tot]=(pt){0,0,0}; 50 P[++tot]=(pt){len,0,0}; 51 sort(P+1,P+tot+1); 52 int last=0; 53 for(int i=1;i<=tot;++i) 54 { 55 if(P[i].type==2) 56 now-=Hash[P[i].num]; 57 else if(P[i].type==1) 58 now+=Hash[P[i].num]; 59 else 60 { 61 bucket[now]+=P[i].x-last; 62 last=P[i].x; 63 } 64 last=P[i].x; 65 } 66 int ans=0; 67 for(map<ull,int>::iterator pt=bucket.begin();pt!=bucket.end();++pt) 68 ans=max(ans,(*pt).second); 69 return ans; 70 } 71 int main() 72 { 73 freopen("master.in","r",stdin); 74 freopen("master.out","w",stdout); 75 ios::sync_with_stdio(false); 76 init(); 77 n=read(),X=read(),Y=read(); 78 for(int i=1;i<=n;++i) 79 a[i].l=read(),b[i].l=read(),a[i].r=read(),b[i].r=read(); 80 cout<<solve(a,X)*solve(b,Y)<<endl; 81 return 0; 82 }
2.一个仙人掌,求$\sigma_{i<j}{f(i,j)*i*j}$,其中f(i,j)表示i,j间的最小割,乘法定义为异或。
首先将每一位分开来考虑。对于一棵树,f(i,j)显然为两点间的最小值,因此将边权从大到小插入,每次统计插入的边两端的答案即可。
对于一个仙人掌,若要割掉一个环,那么环上最小的边一定会被选中。因此对于一个环,将边权最小的边删去,环上其余的边的边权加上其边权即可。
O(nlogw)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long int ll; 4 const int maxn=2E5+5; 5 int n,m; 6 int size,head[maxn]; 7 struct edge 8 { 9 int to,next,w; 10 }E[maxn*2]; 11 int tot,top; 12 inline int read() 13 { 14 char ch=getchar(); 15 while(!isdigit(ch))ch=getchar(); 16 int s=ch-'0';ch=getchar(); 17 while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} 18 return s; 19 } 20 struct pt 21 { 22 int x,y,w,id; 23 pt(int a=0,int b=0,int c=0,int d=0):x(a),y(b),w(c),id(d){} 24 inline bool operator<(const pt&A)const 25 { 26 return w>A.w; 27 } 28 }wait[maxn*2],S[maxn*2]; 29 inline void add(int u,int v,int w) 30 { 31 E[++size].to=v; 32 E[size].next=head[u]; 33 E[size].w=w; 34 head[u]=size; 35 } 36 bool vis[maxn],in[maxn],used[maxn*2]; 37 void dfs(int u,int F) 38 { 39 in[u]=vis[u]=1; 40 for(int i=head[u];i;i=E[i].next) 41 { 42 int v=E[i].to; 43 if(v==F) 44 continue; 45 if(vis[v]) 46 { 47 if(in[v]) 48 { 49 S[++top]=pt(u,v,E[i].w,i); 50 int minn=INT_MAX,pos=0; 51 for(int j=top;;--j) 52 { 53 if(S[j].w<minn) 54 minn=S[j].w,pos=j; 55 used[S[j].id]=1; 56 if(S[j].x==v) 57 break; 58 } 59 for(int j=top;;--j) 60 { 61 if(j!=pos) 62 wait[++tot]=pt(S[j].x,S[j].y,S[j].w+minn); 63 --top; 64 if(S[j].x==v) 65 break; 66 } 67 } 68 continue; 69 } 70 else 71 { 72 S[++top]=pt(u,v,E[i].w,i); 73 dfs(v,u); 74 if(!used[i]) 75 wait[++tot]=pt(u,v,E[i].w),--top; 76 } 77 } 78 in[u]=0; 79 } 80 int sum0[maxn][22],sum1[maxn][22]; 81 struct UFO 82 { 83 int fa[maxn]; 84 inline void clear() 85 { 86 for(int i=0;i<=n;++i) 87 fa[i]=i; 88 } 89 inline int find(int x) 90 { 91 return fa[x]==x?x:fa[x]=find(fa[x]); 92 } 93 inline void merge(int x,int y) 94 { 95 fa[find(x)]=find(y); 96 } 97 }U; 98 inline ll get() 99 { 100 U.clear(); 101 memset(sum0,0,sizeof(sum0)); 102 memset(sum1,0,sizeof(sum1)); 103 for(int d=0;d<21;++d) 104 for(int i=1;i<=n;++i) 105 if(i&(1<<d)) 106 sum1[i][d]=1; 107 else 108 sum0[i][d]=1; 109 ll s=0; 110 for(int i=1;i<=tot;++i) 111 { 112 int x=wait[i].x,y=wait[i].y; 113 x=U.find(x),y=U.find(y); 114 for(int d=0;d<21;++d) 115 { 116 if(wait[i].w&(1<<d)) 117 s+=((ll)sum0[x][d]*sum0[y][d]+(ll)sum1[x][d]*sum1[y][d])<<d; 118 else 119 s+=((ll)sum0[x][d]*sum1[y][d]+(ll)sum1[x][d]*sum0[y][d])<<d; 120 sum0[x][d]+=sum0[y][d]; 121 sum1[x][d]+=sum1[y][d]; 122 } 123 U.merge(y,x); 124 } 125 return s; 126 } 127 inline void solve() 128 { 129 memset(vis,0,sizeof(vis)); 130 memset(head,0,sizeof(head)); 131 memset(used,0,sizeof(used)); 132 size=0; 133 n=read(),m=read(); 134 for(int i=1;i<=m;++i) 135 { 136 int x=read(),y=read(),z=read(); 137 add(x,y,z); 138 add(y,x,z); 139 } 140 top=tot=0; 141 dfs(1,0); 142 // cout<<tot<<endl; 143 // for(int i=1;i<=tot;++i) 144 // cout<<"--- "<<wait[i].x<<" "<<wait[i].y<<" "<<wait[i].w<<endl; 145 // assert(tot+1==n); 146 sort(wait+1,wait+tot+1); 147 ll ans=0; 148 cout<<get()<<endl; 149 } 150 int main() 151 { 152 freopen("okfly.in","r",stdin); 153 freopen("okfly.out","w",stdout); 154 ios::sync_with_stdio(false); 155 int T=read(); 156 while(T--) 157 solve(); 158 return 0; 159 }