当时4/6
补题5/6
意识流6/6
A题:没什么好说的。
B题:一下看错了题意。还以为是统计区间和的正负方案数,结果是乘积。
C题:样例对思路有着很大的启发作用。数一下ab与ba的方案数,把它们简单分个组就好了。。
D题:贪心的思路大致是,从破坏平衡者的角度出发,他可以选择尽量使前一半大(小)于后一半,难得讨论的这么清楚。。。
E题:需要把相同数字都聚拢到一段一段,数字集合只有20,复杂度和做法十分显然,但我还是打假了。考虑DP[i][j]表示要把所有颜色i放到j的前面所需要的ij之间的操作代价。然后状压表示当前已经放完了sta的状态,要把某一颜色放至末尾的操作代价。我也不知道代码怎么会写成这样。。。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const long long inf = 1ll*400000*1ll*400000;
ll d[2002020];
ll cnt[50][50];
vector<int>col[30];
int n;
int main(){
cin >> n;
for (int i = 0; i < n ; i++){
int x; cin>>x;
x--;
col[x].push_back(i);
}
for(int i=0;i<20;i++){
for(int j=0;j<20;j++)if(i!=j && (int)col[i].size()>0 && (int)col[j].size()>0){
int pos2=0;
for(int pos1=0;pos1<(int)col[i].size();pos1++){
while(true){
if(pos2==(int)col[j].size()-1 || col[j][pos2+1]>col[i][pos1])break;
pos2++;
}
if(col[i][pos1]>col[j][pos2])cnt[i][j]+=pos2+1;
}
}
}
for(int mask=0;mask<(1<<20);mask++)d[mask]=inf;
d[0]=0;
for(int mask=0 ;mask<(1<<20);mask++){
vector<int>v;
for(int i=0;i<20;i++)if(mask&(1<<i))v.push_back(i);
for(int i=0;i<20;i++)if((mask&(1<<i))==0){
long long sum=0;
for(int j=0;j<(int)v.size();j++)sum+=cnt[v[j]][i];
d[mask|(1<<i)]=min(d[mask|(1<<i)],d[mask]+sum);
}
}
cout << d[(1<<20)-1]<<endl;
return 0;
}
F题:我觉得我会(大部分)啊。要从p个点中选出若干个点,使得它们之间,两两矛盾的点对必须不能同时存在,两两complaints的点对至少存在一个。同时要选取一个[1,M]之间的频率,使得该频率满足所有被选的节点的区间[Li,Ri]。这样的话对于节点之间的关系,就是朴素2-sat,然后频率范围也才40w,不如对它开一个f必须大于等于i的节点,用所有区间对它进行约束。当然要保证f与f+1的TRUE点之间也是有连边的。
STD CODE:
http://codeforces.com/blog/entry/69815
主要是晚上又可以打div2了,上周div2再不写就。。。。