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 }
View Code

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 }
View Code

 

 posted on 2020-05-26 06:26  GreenDuck  阅读(151)  评论(0编辑  收藏  举报