Atcoder AGC016 簡要題解
阿新 • • 發佈:2018-11-01
+/- Rectangle
對於 ,若 或者 那麼填 ,否則填 ,這樣列出等式後把 選一個最大的就行了, 的範圍夠了。
#include <bits/stdc++.h>
using namespace std;
const double eps=1e-7;
int H,h,W,w;
inline int val(int i,int j,int a,int b) {return ((i%h)||(j%w)) ? a : b;}
int main() {
cin>>H>>W>>h>>w;
if((!(H%h)) && (!(W%w))) return puts("No"),0;
int v=(1e9-1)/(h*w-1);
if((long long)v*(H*W-(H/h)*h*(W/w)*w)<=((H/h)*(W/w))) return puts("No"),0;
puts("Yes");
for(int i=1;i<=H;i++,cout<<'\n')
for(int j=1;j<=W;cout<<val(i,j,v,-v*(h*w-1)-1)<<' ',j++);
}
XOR Replace
設異或和為 並放在 ,發現操作就是交換 ,如果這樣做之後序列和 不一樣那麼肯定無解。否則對於那些不相等的地方,找出一個置換,方案數為置換大小+1(因為第一步要和 先交換),然後發現如果兩個置換某個數相等那麼兩個置換可以合併,於是用個並查集就行了。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e5+50;
int n,a[N],b[N],step;
int anc[N],vis[N];
map <int,int> s;
set <int> pos[N];
inline void lsh(int *c) {
vector <int> vec;
for(int i=1;i<=n+1;i++) vec.push_back(c[i]);
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
for(int i=1;i<=n+1;i++) c[i]=lower_bound(vec.begin(),vec.end(),c[i])-vec.begin()+1;
}
inline int ga(int x) {return (anc[x]==x) ? x : (anc[x]=ga(anc[x]));}
inline void merge(int x,int y) {anc[ga(x)]=ga(y);}
int main() {
n=rd();
for(int i=1;i<=n;i++) a[i]=rd(), a[n+1]^=a[i], ++s[a[i]]; ++s[a[n+1]];
for(int i=1;i<=n;i++) b[i]=rd(), b[n+1]^=b[i], --s[b[i]]; --s[b[n+1]];
for(auto v:s) if(v.second) return puts("-1"),0;
lsh(a); lsh(b); int m=*max_element(a+1,a+n+2);
for(int i=1;i<=n+1;i++)
if((a[i]^b[i]) || i>n) pos[a[i]].insert(i);
for(int i=1;i<=m;i++) anc[i]=i;
for(int i=n+1;i;i--) if(i>n || (a[i]^b[i])){
if(vis[i]) continue;
vector <int> vec;
for(int j=b[i];;) {
int nxt=*pos[j].begin();
pos[j].erase(pos[j].begin());
vec.push_back(nxt);
if(nxt==i) break;
else j=b[nxt];
}
for(auto j:vec) merge(b[j],b[i]), vis[j]=1;
}
memset(vis,0,sizeof(vis));
for(int i=1;i<=n+1;i++) if(a[i]^b[i] || i==n+1) {
if(i<=n) ++step;
if(!vis[ga(a[i])] && (ga(a[i])==a[i])) vis[ga(a[i])]=1, ++step;
}
cout<<step-1<<'\n';
}
Poor Turkeys
傻逼題,不斷維護 表示不能同時存在的對就可以了。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=4e2+5;
int n,m;
bitset <N> sta[N],ban;
int main() {
n=rd(), m=rd();
for(int i=1;i<=m;i++) {
int x=rd(), y=rd();
sta[x]|=sta[y];
sta[y]|=sta[x];
for(int j=1;j<=n;j++) {
int tag1=sta[j].test(x), tag2=sta[j].test(y);
if(tag1) sta[j].set(y);
if(tag2) sta[j].set(x);
}
sta[x].set(y); sta[y].set(x);
}
for(int i=1;i<=n;i++)
if(sta[i][i]) ban[i]=1;
int cnt=0;
for(int i=1;i<=n;i++) if(!ban[i]) {
bitset <N> tp=sta[i];
for(int j=1;j<=n;j++) tp.flip(j);
cnt+=tp.count();
tp&=ban